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" {...@@ -50,35 +50,35 @@ test "zig fmt: respect line breaks after var declarations" {
50 );50 );
51}51}
5252
53//test "zig fmt: multiline string mixed with comments" {53test "zig fmt: multiline string mixed with comments" {
54// try testCanonical(54 try testCanonical(
55// \\const s1 =55 \\const s1 =
56// \\ //\\one56 \\ //\\one
57// \\ \\two)57 \\ \\two)
58// \\ \\three58 \\ \\three
59// \\;59 \\;
60// \\const s2 =60 \\const s2 =
61// \\ \\one61 \\ \\one
62// \\ \\two)62 \\ \\two)
63// \\ //\\three63 \\ //\\three
64// \\;64 \\;
65// \\const s3 =65 \\const s3 =
66// \\ \\one66 \\ \\one
67// \\ //\\two)67 \\ //\\two)
68// \\ \\three68 \\ \\three
69// \\;69 \\;
70// \\const s4 =70 \\const s4 =
71// \\ \\one71 \\ \\one
72// \\ //\\two72 \\ //\\two
73// \\ \\three73 \\ \\three
74// \\ //\\four74 \\ //\\four
75// \\ \\five75 \\ \\five
76// \\;76 \\;
77// \\const a =77 \\const a =
78// \\ 1;78 \\ 1;
79// \\79 \\
80// );80 );
81//}81}
8282
83test "zig fmt: empty file" {83test "zig fmt: empty file" {
84 try testCanonical(84 try testCanonical(
...@@ -974,25 +974,25 @@ test "zig fmt: character literal larger than u8" {...@@ -974,25 +974,25 @@ test "zig fmt: character literal larger than u8" {
974 );974 );
975}975}
976976
977//test "zig fmt: infix operator and then multiline string literal" {977test "zig fmt: infix operator and then multiline string literal" {
978// try testCanonical(978 try testCanonical(
979// \\const x = "" ++979 \\const x = "" ++
980// \\ \\ hi980 \\ \\ hi
981// \\;981 \\;
982// \\982 \\
983// );983 );
984//}984}
985//985
986//test "zig fmt: infix operator and then multiline string literal" {986test "zig fmt: infix operator and then multiline string literal" {
987// try testCanonical(987 try testCanonical(
988// \\const x = "" ++988 \\const x = "" ++
989// \\ \\ hi0989 \\ \\ hi0
990// \\ \\ hi1990 \\ \\ hi1
991// \\ \\ hi2991 \\ \\ hi2
992// \\;992 \\;
993// \\993 \\
994// );994 );
995//}995}
996996
997test "zig fmt: C pointers" {997test "zig fmt: C pointers" {
998 try testCanonical(998 try testCanonical(
...@@ -1725,35 +1725,35 @@ test "zig fmt: struct literal no trailing comma" {...@@ -1725,35 +1725,35 @@ test "zig fmt: struct literal no trailing comma" {
1725// \\1725// \\
1726// );1726// );
1727//}1727//}
1728//1728
1729//test "zig fmt: multiline string with backslash at end of line" {1729test "zig fmt: multiline string with backslash at end of line" {
1730// try testCanonical(1730 try testCanonical(
1731// \\comptime {1731 \\comptime {
1732// \\ err(1732 \\ err(
1733// \\ \\\1733 \\ \\\
1734// \\ );1734 \\ );
1735// \\}1735 \\}
1736// \\1736 \\
1737// );1737 );
1738//}1738}
1739//1739
1740//test "zig fmt: multiline string parameter in fn call with trailing comma" {1740test "zig fmt: multiline string parameter in fn call with trailing comma" {
1741// try testCanonical(1741 try testCanonical(
1742// \\fn foo() void {1742 \\fn foo() void {
1743// \\ try stdout.print(1743 \\ try stdout.print(
1744// \\ \\ZIG_CMAKE_BINARY_DIR {}1744 \\ \\ZIG_CMAKE_BINARY_DIR {}
1745// \\ \\ZIG_C_HEADER_FILES {}1745 \\ \\ZIG_C_HEADER_FILES {}
1746// \\ \\ZIG_DIA_GUIDS_LIB {}1746 \\ \\ZIG_DIA_GUIDS_LIB {}
1747// \\ \\1747 \\ \\
1748// \\ ,1748 \\ ,
1749// \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),1749 \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
1750// \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),1750 \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
1751// \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),1751 \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
1752// \\ );1752 \\ );
1753// \\}1753 \\}
1754// \\1754 \\
1755// );1755 );
1756//}1756}
17571757
1758test "zig fmt: trailing comma on fn call" {1758test "zig fmt: trailing comma on fn call" {
1759 try testCanonical(1759 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...@@ -146,7 +146,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
146 .identifier,146 .identifier,
147 .integer_literal,147 .integer_literal,
148 .float_literal,148 .float_literal,
149 .string_literal,
150 .char_literal,149 .char_literal,
151 .true_literal,150 .true_literal,
152 .false_literal,151 .false_literal,
...@@ -156,6 +155,29 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -156,6 +155,29 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
156 .anyframe_literal,155 .anyframe_literal,
157 => return renderToken(ais, tree, main_tokens[node], space),156 => 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
159 .error_value => {181 .error_value => {
160 try renderToken(ais, tree, main_tokens[node], .none);182 try renderToken(ais, tree, main_tokens[node], .none);
161 try renderToken(ais, tree, main_tokens[node] + 1, .none);183 try renderToken(ais, tree, main_tokens[node] + 1, .none);
...@@ -1821,7 +1843,7 @@ fn renderCall(...@@ -1821,7 +1843,7 @@ fn renderCall(
1821 const last_param = params[params.len - 1];1843 const last_param = params[params.len - 1];
1822 const after_last_param_tok = tree.lastToken(last_param) + 1;1844 const after_last_param_tok = tree.lastToken(last_param) + 1;
1823 if (token_tags[after_last_param_tok] == .comma) {1845 if (token_tags[after_last_param_tok] == .comma) {
1824 ais.pushIndent();1846 ais.pushIndentNextLine();
1825 try renderToken(ais, tree, lparen, Space.newline); // (1847 try renderToken(ais, tree, lparen, Space.newline); // (
1826 for (params) |param_node, i| {1848 for (params) |param_node, i| {
1827 if (i + 1 < params.len) {1849 if (i + 1 < params.len) {
...@@ -1846,6 +1868,7 @@ fn renderCall(...@@ -1846,6 +1868,7 @@ fn renderCall(
1846 return renderToken(ais, tree, after_last_param_tok + 1, space); // )1868 return renderToken(ais, tree, after_last_param_tok + 1, space); // )
1847 }1869 }
18481870
1871 ais.pushIndentNextLine();
1849 try renderToken(ais, tree, lparen, Space.none); // (1872 try renderToken(ais, tree, lparen, Space.none); // (
18501873
1851 for (params) |param_node, i| {1874 for (params) |param_node, i| {
...@@ -1856,6 +1879,8 @@ fn renderCall(...@@ -1856,6 +1879,8 @@ fn renderCall(
1856 try renderToken(ais, tree, comma, Space.space);1879 try renderToken(ais, tree, comma, Space.space);
1857 }1880 }
1858 }1881 }
1882
1883 ais.popIndent();
1859 return renderToken(ais, tree, after_last_param_tok, space); // )1884 return renderToken(ais, tree, after_last_param_tok, space); // )
1860}1885}
18611886
...@@ -1907,7 +1932,8 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp...@@ -1907,7 +1932,8 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp
1907 const token_starts = tree.tokens.items(.start);1932 const token_starts = tree.tokens.items(.start);
19081933
1909 const token_start = token_starts[token_index];1934 const token_start = token_starts[token_index];
1910 const lexeme = tree.tokenSlice(token_index);1935 const lexeme = tokenSliceForRender(tree, token_index);
1936
1911 try ais.writer().writeAll(lexeme);1937 try ais.writer().writeAll(lexeme);
19121938
1913 if (space == .no_comment) return;1939 if (space == .no_comment) return;
...@@ -1991,7 +2017,7 @@ fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenInde...@@ -1991,7 +2017,7 @@ fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenInde
1991 const prev_token_end = if (token_index == 0)2017 const prev_token_end = if (token_index == 0)
1992 02018 0
1993 else2019 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
1996 // If there is a comment present, it will handle the empty line2022 // If there is a comment present, it will handle the empty line
1997 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;2023 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...@@ -2034,6 +2060,15 @@ fn renderDocComments(ais: *Ais, tree: ast.Tree, end_token: ast.TokenIndex) Error
2034 }2060 }
2035}2061}
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
2037fn nodeIsBlock(tag: ast.Node.Tag) bool {2072fn nodeIsBlock(tag: ast.Node.Tag) bool {
2038 return switch (tag) {2073 return switch (tag) {
2039 .block,2074 .block,