Commit bb89c619ed

Andrew Kelley <andrew@ziglang.org>
2021-02-24 01:00:33
zig fmt: multiline string literals + array init
1 parent 6f4a1ba
Changed files (2)
lib/std/zig/parser_test.zig
@@ -3986,68 +3986,71 @@ 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 {
-//        \\    var a = .{.{.{.{.{.{.{.{
-//        \\        0,
-//        \\    }}}}}}}};
-//        \\    myFunc(.{
-//        \\        "aaaaaaa",                           "bbbbbb",                            "ccccc",
-//        \\        "dddd",                              ("eee"),                             ("fff"),
-//        \\        ("gggg"),
-//        \\        // Line comment
-//        \\        \\Multiline String Literals can be quite long
-//        \\        ,
-//        \\        \\Multiline String Literals can be quite long
-//        \\        \\Multiline String Literals can be quite long
-//        \\        ,
-//        \\        \\Multiline String Literals can be quite long
-//        \\        \\Multiline String Literals can be quite long
-//        \\        \\Multiline String Literals can be quite long
-//        \\        \\Multiline String Literals can be quite long
-//        \\        ,
-//        \\        (
-//        \\            \\Multiline String Literals can be quite long
-//        \\        ),
-//        \\        .{
-//        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\        },
-//        \\        .{(
-//        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\        )},
-//        \\        .{
-//        \\            "xxxxxxx", "xxx",
-//        \\            (
-//        \\                \\ xxx
-//        \\            ),
-//        \\            "xxx",     "xxx",
-//        \\        },
-//        \\        .{ "xxxxxxx", "xxx", "xxx", "xxx" }, .{ "xxxxxxx", "xxx", "xxx", "xxx" },
-//        \\        "aaaaaaa", "bbbbbb", "ccccc", // -
-//        \\        "dddd",    ("eee"),  ("fff"),
-//        \\        .{
-//        \\            "xxx",            "xxx",
-//        \\            (
-//        \\                \\ xxx
-//        \\            ),
-//        \\            "xxxxxxxxxxxxxx", "xxx",
-//        \\        },
-//        \\        .{
-//        \\            (
-//        \\                \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\            ),
-//        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\        },
-//        \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-//        \\    });
-//        \\}
-//        \\
-//    );
-//}
+test "zig fmt: multiline string literals should play nice with array initializers" {
+    try testCanonical(
+        \\fn main() void {
+        \\    var a = .{.{.{.{.{.{.{.{
+        \\        0,
+        \\    }}}}}}}};
+        \\    myFunc(.{
+        \\        "aaaaaaa",                           "bbbbbb", "ccccc",
+        \\        "dddd",                              ("eee"),  ("fff"),
+        \\        ("gggg"),
+        \\        // Line comment
+        \\        \\Multiline String Literals can be quite long
+        \\        ,
+        \\        \\Multiline String Literals can be quite long
+        \\        \\Multiline String Literals can be quite long
+        \\        ,
+        \\        \\Multiline String Literals can be quite long
+        \\        \\Multiline String Literals can be quite long
+        \\        \\Multiline String Literals can be quite long
+        \\        \\Multiline String Literals can be quite long
+        \\        ,
+        \\        (
+        \\            \\Multiline String Literals can be quite long
+        \\        ),
+        \\        .{
+        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\        },
+        \\        .{(
+        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\        )},
+        \\        .{
+        \\            "xxxxxxx", "xxx",
+        \\            (
+        \\                \\ xxx
+        \\            ),
+        \\            "xxx",
+        \\            "xxx",
+        \\        },
+        \\        .{ "xxxxxxx", "xxx", "xxx", "xxx" },
+        \\        .{ "xxxxxxx", "xxx", "xxx", "xxx" },
+        \\        "aaaaaaa", "bbbbbb", "ccccc", // -
+        \\        "dddd",    ("eee"),  ("fff"),
+        \\        .{
+        \\            "xxx",            "xxx",
+        \\            (
+        \\                \\ xxx
+        \\            ),
+        \\            "xxxxxxxxxxxxxx",
+        \\            "xxx",
+        \\        },
+        \\        .{
+        \\            (
+        \\                \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\            ),
+        \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\        },
+        \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+        \\    });
+        \\}
+        \\
+    );
+}
 
 test "zig fmt: use of comments and multiline string literals may force the parameters over multiple lines" {
     try testCanonical(
lib/std/zig/render.zig
@@ -1686,6 +1686,19 @@ fn renderArrayInit(
     const trailing_comma = token_tags[last_elem_token + 1] == .comma;
     const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1;
     assert(token_tags[rbrace] == .r_brace);
+
+    if (array_init.ast.elements.len == 1) {
+        const only_elem = array_init.ast.elements[0];
+        const first_token = tree.firstToken(only_elem);
+        if (token_tags[first_token] != .multiline_string_literal_line and
+            !anythingBetween(tree, last_elem_token, rbrace))
+        {
+            try renderToken(ais, tree, array_init.ast.lbrace, .none);
+            try renderExpression(gpa, ais, tree, only_elem, .none);
+            return renderToken(ais, tree, rbrace, space);
+        }
+    }
+
     const contains_newlines = !tree.tokensOnSameLine(array_init.ast.lbrace, rbrace);
 
     if (!trailing_comma and !contains_newlines) {
@@ -2353,6 +2366,19 @@ fn hasSameLineComment(tree: ast.Tree, token_index: ast.TokenIndex) bool {
     return false;
 }
 
+/// Returns `true` if and only if there are any tokens or line comments between
+/// start_token and end_token.
+fn anythingBetween(tree: ast.Tree, start_token: ast.TokenIndex, end_token: ast.TokenIndex) bool {
+    if (start_token + 1 != end_token) return true;
+    const token_starts = tree.tokens.items(.start);
+    const between_source = tree.source[token_starts[start_token]..token_starts[start_token + 1]];
+    for (between_source) |byte| switch (byte) {
+        '/' => return true,
+        else => continue,
+    };
+    return false;
+}
+
 fn writeFixingWhitespace(writer: std.ArrayList(u8).Writer, slice: []const u8) Error!void {
     for (slice) |byte| switch (byte) {
         '\t' => try writer.writeAll(" " ** 4),