authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-02-13 15:23:24+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-13 16:57:34-08:00
log24798b84ad818a4c6d6a6ee3e215ccbc49293b81
tree0fa712dd8162c5f7f91bbf6f63ce89a98cc6eb29
parent75ba8d8db6d3c067fd8f9c8d32e6fea7c3b9343b

zig fmt: implement multiline string literals


2 files changed, 116 insertions(+), 81 deletions(-)

lib/std/zig/parser_test.zig+77-77
......@@ -50,35 +50,35 @@ test "zig fmt: respect line breaks after var declarations" {
5050 );
5151}
5252
53//test "zig fmt: multiline string mixed with comments" {
54// try testCanonical(
55// \\const s1 =
56// \\ //\\one
57// \\ \\two)
58// \\ \\three
59// \\;
60// \\const s2 =
61// \\ \\one
62// \\ \\two)
63// \\ //\\three
64// \\;
65// \\const s3 =
66// \\ \\one
67// \\ //\\two)
68// \\ \\three
69// \\;
70// \\const s4 =
71// \\ \\one
72// \\ //\\two
73// \\ \\three
74// \\ //\\four
75// \\ \\five
76// \\;
77// \\const a =
78// \\ 1;
79// \\
80// );
81//}
53test "zig fmt: multiline string mixed with comments" {
54 try testCanonical(
55 \\const s1 =
56 \\ //\\one
57 \\ \\two)
58 \\ \\three
59 \\;
60 \\const s2 =
61 \\ \\one
62 \\ \\two)
63 \\ //\\three
64 \\;
65 \\const s3 =
66 \\ \\one
67 \\ //\\two)
68 \\ \\three
69 \\;
70 \\const s4 =
71 \\ \\one
72 \\ //\\two
73 \\ \\three
74 \\ //\\four
75 \\ \\five
76 \\;
77 \\const a =
78 \\ 1;
79 \\
80 );
81}
8282
8383test "zig fmt: empty file" {
8484 try testCanonical(
......@@ -974,25 +974,25 @@ test "zig fmt: character literal larger than u8" {
974974 );
975975}
976976
977//test "zig fmt: infix operator and then multiline string literal" {
978// try testCanonical(
979// \\const x = "" ++
980// \\ \\ hi
981// \\;
982// \\
983// );
984//}
985//
986//test "zig fmt: infix operator and then multiline string literal" {
987// try testCanonical(
988// \\const x = "" ++
989// \\ \\ hi0
990// \\ \\ hi1
991// \\ \\ hi2
992// \\;
993// \\
994// );
995//}
977test "zig fmt: infix operator and then multiline string literal" {
978 try testCanonical(
979 \\const x = "" ++
980 \\ \\ hi
981 \\;
982 \\
983 );
984}
985
986test "zig fmt: infix operator and then multiline string literal" {
987 try testCanonical(
988 \\const x = "" ++
989 \\ \\ hi0
990 \\ \\ hi1
991 \\ \\ hi2
992 \\;
993 \\
994 );
995}
996996
997997test "zig fmt: C pointers" {
998998 try testCanonical(
......@@ -1725,35 +1725,35 @@ test "zig fmt: struct literal no trailing comma" {
17251725// \\
17261726// );
17271727//}
1728//
1729//test "zig fmt: multiline string with backslash at end of line" {
1730// try testCanonical(
1731// \\comptime {
1732// \\ err(
1733// \\ \\\
1734// \\ );
1735// \\}
1736// \\
1737// );
1738//}
1739//
1740//test "zig fmt: multiline string parameter in fn call with trailing comma" {
1741// try testCanonical(
1742// \\fn foo() void {
1743// \\ try stdout.print(
1744// \\ \\ZIG_CMAKE_BINARY_DIR {}
1745// \\ \\ZIG_C_HEADER_FILES {}
1746// \\ \\ZIG_DIA_GUIDS_LIB {}
1747// \\ \\
1748// \\ ,
1749// \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
1750// \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
1751// \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
1752// \\ );
1753// \\}
1754// \\
1755// );
1756//}
1728
1729test "zig fmt: multiline string with backslash at end of line" {
1730 try testCanonical(
1731 \\comptime {
1732 \\ err(
1733 \\ \\\
1734 \\ );
1735 \\}
1736 \\
1737 );
1738}
1739
1740test "zig fmt: multiline string parameter in fn call with trailing comma" {
1741 try testCanonical(
1742 \\fn foo() void {
1743 \\ try stdout.print(
1744 \\ \\ZIG_CMAKE_BINARY_DIR {}
1745 \\ \\ZIG_C_HEADER_FILES {}
1746 \\ \\ZIG_DIA_GUIDS_LIB {}
1747 \\ \\
1748 \\ ,
1749 \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
1750 \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
1751 \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
1752 \\ );
1753 \\}
1754 \\
1755 );
1756}
17571757
17581758test "zig fmt: trailing comma on fn call" {
17591759 try testCanonical(
lib/std/zig/render.zig+39-4
......@@ -146,7 +146,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
146146 .identifier,
147147 .integer_literal,
148148 .float_literal,
149 .string_literal,
150149 .char_literal,
151150 .true_literal,
152151 .false_literal,
......@@ -156,6 +155,29 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
156155 .anyframe_literal,
157156 => return renderToken(ais, tree, main_tokens[node], space),
158157
158 .string_literal => switch (token_tags[main_tokens[node]]) {
159 .string_literal => try renderToken(ais, tree, main_tokens[node], space),
160
161 .multiline_string_literal_line => {
162 var locked_indents = ais.lockOneShotIndent();
163 try ais.maybeInsertNewline();
164
165 var i = datas[node].lhs;
166 while (i <= datas[node].rhs) : (i += 1) try renderToken(ais, tree, i, .newline);
167
168 while (locked_indents > 0) : (locked_indents -= 1) ais.popIndent();
169
170 switch (space) {
171 .none => {},
172 .semicolon => if (token_tags[i] == .semicolon) try renderToken(ais, tree, i, .newline),
173 .comma => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .newline),
174 .comma_space => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .space),
175 else => unreachable,
176 }
177 },
178 else => unreachable,
179 },
180
159181 .error_value => {
160182 try renderToken(ais, tree, main_tokens[node], .none);
161183 try renderToken(ais, tree, main_tokens[node] + 1, .none);
......@@ -1821,7 +1843,7 @@ fn renderCall(
18211843 const last_param = params[params.len - 1];
18221844 const after_last_param_tok = tree.lastToken(last_param) + 1;
18231845 if (token_tags[after_last_param_tok] == .comma) {
1824 ais.pushIndent();
1846 ais.pushIndentNextLine();
18251847 try renderToken(ais, tree, lparen, Space.newline); // (
18261848 for (params) |param_node, i| {
18271849 if (i + 1 < params.len) {
......@@ -1846,6 +1868,7 @@ fn renderCall(
18461868 return renderToken(ais, tree, after_last_param_tok + 1, space); // )
18471869 }
18481870
1871 ais.pushIndentNextLine();
18491872 try renderToken(ais, tree, lparen, Space.none); // (
18501873
18511874 for (params) |param_node, i| {
......@@ -1856,6 +1879,8 @@ fn renderCall(
18561879 try renderToken(ais, tree, comma, Space.space);
18571880 }
18581881 }
1882
1883 ais.popIndent();
18591884 return renderToken(ais, tree, after_last_param_tok, space); // )
18601885}
18611886
......@@ -1907,7 +1932,8 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp
19071932 const token_starts = tree.tokens.items(.start);
19081933
19091934 const token_start = token_starts[token_index];
1910 const lexeme = tree.tokenSlice(token_index);
1935 const lexeme = tokenSliceForRender(tree, token_index);
1936
19111937 try ais.writer().writeAll(lexeme);
19121938
19131939 if (space == .no_comment) return;
......@@ -1991,7 +2017,7 @@ fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenInde
19912017 const prev_token_end = if (token_index == 0)
19922018 0
19932019 else
1994 token_starts[token_index - 1] + tree.tokenSlice(token_index - 1).len;
2020 token_starts[token_index - 1] + tokenSliceForRender(tree, token_index - 1).len;
19952021
19962022 // If there is a comment present, it will handle the empty line
19972023 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;
......@@ -2034,6 +2060,15 @@ fn renderDocComments(ais: *Ais, tree: ast.Tree, end_token: ast.TokenIndex) Error
20342060 }
20352061}
20362062
2063fn tokenSliceForRender(tree: ast.Tree, token_index: ast.TokenIndex) []const u8 {
2064 var ret = tree.tokenSlice(token_index);
2065 if (tree.tokens.items(.tag)[token_index] == .multiline_string_literal_line) {
2066 assert(ret[ret.len - 1] == '\n');
2067 ret.len -= 1;
2068 }
2069 return ret;
2070}
2071
20372072fn nodeIsBlock(tag: ast.Node.Tag) bool {
20382073 return switch (tag) {
20392074 .block,