authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-02-11 22:38:59+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-11 15:49:49-08:00
logfaa3fa65ac89b774b26bdd0ea4ac70861b29d0b4
treef3fe6d80be3190224458b711f7c5ffcf90c7c0da
parentb6448a533d4465c226b7b8613806ff0673261d6a

zig fmt: implement line comments


2 files changed, 595 insertions(+), 660 deletions(-)

lib/std/zig/parser_test.zig+531-558
...@@ -663,7 +663,9 @@ test "zig fmt: anon list literal 3 element comma" {...@@ -663,7 +663,9 @@ test "zig fmt: anon list literal 3 element comma" {
663 \\test {663 \\test {
664 \\ const x = .{664 \\ const x = .{
665 \\ a,665 \\ a,
666 \\ // foo
666 \\ b,667 \\ b,
668 \\
667 \\ c,669 \\ c,
668 \\ };670 \\ };
669 \\}671 \\}
...@@ -874,20 +876,20 @@ test "zig fmt: enum literal" {...@@ -874,20 +876,20 @@ test "zig fmt: enum literal" {
874 );876 );
875}877}
876878
877//test "zig fmt: enum literal inside array literal" {879test "zig fmt: enum literal inside array literal" {
878// try testCanonical(880 try testCanonical(
879// \\test "enums in arrays" {881 \\test "enums in arrays" {
880// \\ var colors = []Color{.Green};882 \\ var colors = []Color{.Green};
881// \\ colors = []Colors{ .Green, .Cyan };883 \\ colors = []Colors{ .Green, .Cyan };
882// \\ colors = []Colors{884 \\ colors = []Colors{
883// \\ .Grey,885 \\ .Grey,
884// \\ .Green,886 \\ .Green,
885// \\ .Cyan,887 \\ .Cyan,
886// \\ };888 \\ };
887// \\}889 \\}
888// \\890 \\
889// );891 );
890//}892}
891893
892test "zig fmt: character literal larger than u8" {894test "zig fmt: character literal larger than u8" {
893 try testCanonical(895 try testCanonical(
...@@ -954,56 +956,56 @@ test "zig fmt: linksection" {...@@ -954,56 +956,56 @@ test "zig fmt: linksection" {
954// \\956// \\
955// );957// );
956//}958//}
957//959
958//test "zig fmt: correctly space struct fields with doc comments" {960test "zig fmt: correctly space struct fields with doc comments" {
959// try testTransform(961 try testTransform(
960// \\pub const S = struct {962 \\pub const S = struct {
961// \\ /// A963 \\ /// A
962// \\ a: u8,964 \\ a: u8,
963// \\ /// B965 \\ /// B
964// \\ /// B (cont)966 \\ /// B (cont)
965// \\ b: u8,967 \\ b: u8,
966// \\968 \\
967// \\969 \\
968// \\ /// C970 \\ /// C
969// \\ c: u8,971 \\ c: u8,
970// \\};972 \\};
971// \\973 \\
972// ,974 ,
973// \\pub const S = struct {975 \\pub const S = struct {
974// \\ /// A976 \\ /// A
975// \\ a: u8,977 \\ a: u8,
976// \\ /// B978 \\ /// B
977// \\ /// B (cont)979 \\ /// B (cont)
978// \\ b: u8,980 \\ b: u8,
979// \\981 \\
980// \\ /// C982 \\ /// C
981// \\ c: u8,983 \\ c: u8,
982// \\};984 \\};
983// \\985 \\
984// );986 );
985//}987}
986//988
987//test "zig fmt: doc comments on param decl" {989test "zig fmt: doc comments on param decl" {
988// try testCanonical(990 try testCanonical(
989// \\pub const Allocator = struct {991 \\pub const Allocator = struct {
990// \\ shrinkFn: fn (992 \\ shrinkFn: fn (
991// \\ self: *Allocator,993 \\ self: *Allocator,
992// \\ /// Guaranteed to be the same as what was returned from most recent call to994 \\ /// Guaranteed to be the same as what was returned from most recent call to
993// \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.995 \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
994// \\ old_mem: []u8,996 \\ old_mem: []u8,
995// \\ /// Guaranteed to be the same as what was returned from most recent call to997 \\ /// Guaranteed to be the same as what was returned from most recent call to
996// \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.998 \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
997// \\ old_alignment: u29,999 \\ old_alignment: u29,
998// \\ /// Guaranteed to be less than or equal to `old_mem.len`.1000 \\ /// Guaranteed to be less than or equal to `old_mem.len`.
999// \\ new_byte_count: usize,1001 \\ new_byte_count: usize,
1000// \\ /// Guaranteed to be less than or equal to `old_alignment`.1002 \\ /// Guaranteed to be less than or equal to `old_alignment`.
1001// \\ new_alignment: u29,1003 \\ new_alignment: u29,
1002// \\ ) []u8,1004 \\ ) []u8,
1003// \\};1005 \\};
1004// \\1006 \\
1005// );1007 );
1006//}1008}
10071009
1008test "zig fmt: aligned struct field" {1010test "zig fmt: aligned struct field" {
1009 try testCanonical(1011 try testCanonical(
...@@ -1142,13 +1144,13 @@ test "zig fmt: aligned struct field" {...@@ -1142,13 +1144,13 @@ test "zig fmt: aligned struct field" {
1142// \\1144// \\
1143// );1145// );
1144//}1146//}
1145//1147
1146//test "zig fmt: pointer of unknown length" {1148test "zig fmt: pointer of unknown length" {
1147// try testCanonical(1149 try testCanonical(
1148// \\fn foo(ptr: [*]u8) void {}1150 \\fn foo(ptr: [*]u8) void {}
1149// \\1151 \\
1150// );1152 );
1151//}1153}
11521154
1153test "zig fmt: spaces around slice operator" {1155test "zig fmt: spaces around slice operator" {
1154 try testCanonical(1156 try testCanonical(
...@@ -1370,25 +1372,25 @@ test "zig fmt: async call in if condition" {...@@ -1370,25 +1372,25 @@ test "zig fmt: async call in if condition" {
1370// \\1372// \\
1371// );1373// );
1372//}1374//}
1373//1375
1374//test "zig fmt: if-else with comment before else" {1376test "zig fmt: if-else with comment before else" {
1375// try testCanonical(1377 try testCanonical(
1376// \\comptime {1378 \\comptime {
1377// \\ // cexp(finite|nan +- i inf|nan) = nan + i nan1379 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
1378// \\ if ((hx & 0x7fffffff) != 0x7f800000) {1380 \\ if ((hx & 0x7fffffff) != 0x7f800000) {
1379// \\ return Complex(f32).new(y - y, y - y);1381 \\ return Complex(f32).new(y - y, y - y);
1380// \\ } // cexp(-inf +- i inf|nan) = 0 + i01382 \\ } // cexp(-inf +- i inf|nan) = 0 + i0
1381// \\ else if (hx & 0x80000000 != 0) {1383 \\ else if (hx & 0x80000000 != 0) {
1382// \\ return Complex(f32).new(0, 0);1384 \\ return Complex(f32).new(0, 0);
1383// \\ } // cexp(+inf +- i inf|nan) = inf + i nan1385 \\ } // cexp(+inf +- i inf|nan) = inf + i nan
1384// \\ else {1386 \\ else {
1385// \\ return Complex(f32).new(x, y - y);1387 \\ return Complex(f32).new(x, y - y);
1386// \\ }1388 \\ }
1387// \\}1389 \\}
1388// \\1390 \\
1389// );1391 );
1390//}1392}
1391//1393
1392//test "zig fmt: if nested" {1394//test "zig fmt: if nested" {
1393// try testCanonical(1395// try testCanonical(
1394// \\pub fn foo() void {1396// \\pub fn foo() void {
...@@ -1467,17 +1469,17 @@ test "zig fmt: enum decl with no trailing comma" {...@@ -1467,17 +1469,17 @@ test "zig fmt: enum decl with no trailing comma" {
1467 );1469 );
1468}1470}
14691471
1470//test "zig fmt: switch comment before prong" {1472test "zig fmt: switch comment before prong" {
1471// try testCanonical(1473 try testCanonical(
1472// \\comptime {1474 \\comptime {
1473// \\ switch (a) {1475 \\ switch (a) {
1474// \\ // hi1476 \\ // hi
1475// \\ 0 => {},1477 \\ 0 => {},
1476// \\ }1478 \\ }
1477// \\}1479 \\}
1478// \\1480 \\
1479// );1481 );
1480//}1482}
14811483
1482test "zig fmt: struct literal no trailing comma" {1484test "zig fmt: struct literal no trailing comma" {
1483 try testTransform(1485 try testTransform(
...@@ -1709,17 +1711,17 @@ test "zig fmt: multi line arguments without last comma" {...@@ -1709,17 +1711,17 @@ test "zig fmt: multi line arguments without last comma" {
1709 );1711 );
1710}1712}
17111713
1712//test "zig fmt: empty block with only comment" {1714test "zig fmt: empty block with only comment" {
1713// try testCanonical(1715 try testCanonical(
1714// \\comptime {1716 \\comptime {
1715// \\ {1717 \\ {
1716// \\ // comment1718 \\ // comment
1717// \\ }1719 \\ }
1718// \\}1720 \\}
1719// \\1721 \\
1720// );1722 );
1721//}1723}
1722//1724
1723//test "zig fmt: no trailing comma on struct decl" {1725//test "zig fmt: no trailing comma on struct decl" {
1724// try testCanonical(1726// try testCanonical(
1725// \\const RoundParam = struct {1727// \\const RoundParam = struct {
...@@ -1781,15 +1783,15 @@ test "zig fmt: extra newlines at the end" {...@@ -1781,15 +1783,15 @@ test "zig fmt: extra newlines at the end" {
1781// \\1783// \\
1782// );1784// );
1783//}1785//}
1784//1786
1785//test "zig fmt: nested struct literal with one item" {1787test "zig fmt: nested struct literal with one item" {
1786// try testCanonical(1788 try testCanonical(
1787// \\const a = foo{1789 \\const a = foo{
1788// \\ .item = bar{ .a = b },1790 \\ .item = bar{ .a = b },
1789// \\};1791 \\};
1790// \\1792 \\
1791// );1793 );
1792//}1794}
17931795
1794test "zig fmt: switch cases trailing comma" {1796test "zig fmt: switch cases trailing comma" {
1795 try testTransform(1797 try testTransform(
...@@ -1848,26 +1850,26 @@ test "zig fmt: slice align" {...@@ -1848,26 +1850,26 @@ test "zig fmt: slice align" {
1848// \\1850// \\
1849// );1851// );
1850//}1852//}
1851//1853
1852//test "zig fmt: first thing in file is line comment" {1854test "zig fmt: first thing in file is line comment" {
1853// try testCanonical(1855 try testCanonical(
1854// \\// Introspection and determination of system libraries needed by zig.1856 \\// Introspection and determination of system libraries needed by zig.
1855// \\1857 \\
1856// \\// Introspection and determination of system libraries needed by zig.1858 \\// Introspection and determination of system libraries needed by zig.
1857// \\1859 \\
1858// \\const std = @import("std");1860 \\const std = @import("std");
1859// \\1861 \\
1860// );1862 );
1861//}1863}
1862//1864
1863//test "zig fmt: line comment after doc comment" {1865test "zig fmt: line comment after doc comment" {
1864// try testCanonical(1866 try testCanonical(
1865// \\/// doc comment1867 \\/// doc comment
1866// \\// line comment1868 \\// line comment
1867// \\fn foo() void {}1869 \\fn foo() void {}
1868// \\1870 \\
1869// );1871 );
1870//}1872}
18711873
1872test "zig fmt: bit field alignment" {1874test "zig fmt: bit field alignment" {
1873 try testCanonical(1875 try testCanonical(
...@@ -1928,27 +1930,27 @@ test "zig fmt: nested blocks" {...@@ -1928,27 +1930,27 @@ test "zig fmt: nested blocks" {
1928 );1930 );
1929}1931}
19301932
1931//test "zig fmt: block with same line comment after end brace" {1933test "zig fmt: block with same line comment after end brace" {
1932// try testCanonical(1934 try testCanonical(
1933// \\comptime {1935 \\comptime {
1934// \\ {1936 \\ {
1935// \\ b();1937 \\ b();
1936// \\ } // comment1938 \\ } // comment
1937// \\}1939 \\}
1938// \\1940 \\
1939// );1941 );
1940//}1942}
1941//1943
1942//test "zig fmt: statements with comment between" {1944test "zig fmt: statements with comment between" {
1943// try testCanonical(1945 try testCanonical(
1944// \\comptime {1946 \\comptime {
1945// \\ a = b;1947 \\ a = b;
1946// \\ // comment1948 \\ // comment
1947// \\ a = b;1949 \\ a = b;
1948// \\}1950 \\}
1949// \\1951 \\
1950// );1952 );
1951//}1953}
19521954
1953test "zig fmt: statements with empty line between" {1955test "zig fmt: statements with empty line between" {
1954 try testCanonical(1956 try testCanonical(
...@@ -1969,60 +1971,60 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {...@@ -1969,60 +1971,60 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {
1969 );1971 );
1970}1972}
19711973
1972//test "zig fmt: comment after if before another if" {1974test "zig fmt: comment after if before another if" {
1973// try testCanonical(1975 try testCanonical(
1974// \\test "aoeu" {1976 \\test "aoeu" {
1975// \\ // comment1977 \\ // comment
1976// \\ if (x) {1978 \\ if (x) {
1977// \\ bar();1979 \\ bar();
1978// \\ }1980 \\ }
1979// \\}1981 \\}
1980// \\1982 \\
1981// \\test "aoeu" {1983 \\test "aoeu" {
1982// \\ if (x) {1984 \\ if (x) {
1983// \\ foo();1985 \\ foo();
1984// \\ }1986 \\ }
1985// \\ // comment1987 \\ // comment
1986// \\ if (x) {1988 \\ if (x) {
1987// \\ bar();1989 \\ bar();
1988// \\ }1990 \\ }
1989// \\}1991 \\}
1990// \\1992 \\
1991// );1993 );
1992//}1994}
1993//1995
1994//test "zig fmt: line comment between if block and else keyword" {1996test "zig fmt: line comment between if block and else keyword" {
1995// try testCanonical(1997 try testCanonical(
1996// \\test "aoeu" {1998 \\test "aoeu" {
1997// \\ // cexp(finite|nan +- i inf|nan) = nan + i nan1999 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
1998// \\ if ((hx & 0x7fffffff) != 0x7f800000) {2000 \\ if ((hx & 0x7fffffff) != 0x7f800000) {
1999// \\ return Complex(f32).new(y - y, y - y);2001 \\ return Complex(f32).new(y - y, y - y);
2000// \\ }2002 \\ }
2001// \\ // cexp(-inf +- i inf|nan) = 0 + i02003 \\ // cexp(-inf +- i inf|nan) = 0 + i0
2002// \\ else if (hx & 0x80000000 != 0) {2004 \\ else if (hx & 0x80000000 != 0) {
2003// \\ return Complex(f32).new(0, 0);2005 \\ return Complex(f32).new(0, 0);
2004// \\ }2006 \\ }
2005// \\ // cexp(+inf +- i inf|nan) = inf + i nan2007 \\ // cexp(+inf +- i inf|nan) = inf + i nan
2006// \\ // another comment2008 \\ // another comment
2007// \\ else {2009 \\ else {
2008// \\ return Complex(f32).new(x, y - y);2010 \\ return Complex(f32).new(x, y - y);
2009// \\ }2011 \\ }
2010// \\}2012 \\}
2011// \\2013 \\
2012// );2014 );
2013//}2015}
2014//2016
2015//test "zig fmt: same line comments in expression" {2017test "zig fmt: same line comments in expression" {
2016// try testCanonical(2018 try testCanonical(
2017// \\test "aoeu" {2019 \\test "aoeu" {
2018// \\ const x = ( // a2020 \\ const x = ( // a
2019// \\ 0 // b2021 \\ 0 // b
2020// \\ ); // c2022 \\ ); // c
2021// \\}2023 \\}
2022// \\2024 \\
2023// );2025 );
2024//}2026}
2025//2027
2026//test "zig fmt: add comma on last switch prong" {2028//test "zig fmt: add comma on last switch prong" {
2027// try testTransform(2029// try testTransform(
2028// \\test "aoeu" {2030// \\test "aoeu" {
...@@ -2051,127 +2053,126 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {...@@ -2051,127 +2053,126 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {
2051// \\2053// \\
2052// );2054// );
2053//}2055//}
2054//
2055//test "zig fmt: same-line comment after a statement" {
2056// try testCanonical(
2057// \\test "" {
2058// \\ a = b;
2059// \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
2060// \\ a = b;
2061// \\}
2062// \\
2063// );
2064//}
2065//
2066//test "zig fmt: same-line comment after var decl in struct" {
2067// try testCanonical(
2068// \\pub const vfs_cap_data = extern struct {
2069// \\ const Data = struct {}; // when on disk.
2070// \\};
2071// \\
2072// );
2073//}
2074//
2075//test "zig fmt: same-line comment after field decl" {
2076// try testCanonical(
2077// \\pub const dirent = extern struct {
2078// \\ d_name: u8,
2079// \\ d_name: u8, // comment 1
2080// \\ d_name: u8,
2081// \\ d_name: u8, // comment 2
2082// \\ d_name: u8,
2083// \\};
2084// \\
2085// );
2086//}
2087//
2088//test "zig fmt: same-line comment after switch prong" {
2089// try testCanonical(
2090// \\test "" {
2091// \\ switch (err) {
2092// \\ error.PathAlreadyExists => {}, // comment 2
2093// \\ else => return err, // comment 1
2094// \\ }
2095// \\}
2096// \\
2097// );
2098//}
2099//
2100//test "zig fmt: same-line comment after non-block if expression" {
2101// try testCanonical(
2102// \\comptime {
2103// \\ if (sr > n_uword_bits - 1) // d > r
2104// \\ return 0;
2105// \\}
2106// \\
2107// );
2108//}
2109//
2110//test "zig fmt: same-line comment on comptime expression" {
2111// try testCanonical(
2112// \\test "" {
2113// \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
2114// \\}
2115// \\
2116// );
2117//}
21182056
2119test "zig fmt: switch with empty body" {2057test "zig fmt: same-line comment after a statement" {
2058 try testCanonical(
2059 \\test "" {
2060 \\ a = b;
2061 \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
2062 \\ a = b;
2063 \\}
2064 \\
2065 );
2066}
2067
2068test "zig fmt: same-line comment after var decl in struct" {
2069 try testCanonical(
2070 \\pub const vfs_cap_data = extern struct {
2071 \\ const Data = struct {}; // when on disk.
2072 \\};
2073 \\
2074 );
2075}
2076
2077test "zig fmt: same-line comment after field decl" {
2078 try testCanonical(
2079 \\pub const dirent = extern struct {
2080 \\ d_name: u8,
2081 \\ d_name: u8, // comment 1
2082 \\ d_name: u8,
2083 \\ d_name: u8, // comment 2
2084 \\ d_name: u8,
2085 \\};
2086 \\
2087 );
2088}
2089
2090test "zig fmt: same-line comment after switch prong" {
2091 try testCanonical(
2092 \\test "" {
2093 \\ switch (err) {
2094 \\ error.PathAlreadyExists => {}, // comment 2
2095 \\ else => return err, // comment 1
2096 \\ }
2097 \\}
2098 \\
2099 );
2100}
2101
2102test "zig fmt: same-line comment after non-block if expression" {
2103 try testCanonical(
2104 \\comptime {
2105 \\ if (sr > n_uword_bits - 1) // d > r
2106 \\ return 0;
2107 \\}
2108 \\
2109 );
2110}
2111
2112test "zig fmt: same-line comment on comptime expression" {
2113 try testCanonical(
2114 \\test "" {
2115 \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
2116 \\}
2117 \\
2118 );
2119}
2120
2121test "zig fmt: switch with empty body" {
2122 try testCanonical(
2123 \\test "" {
2124 \\ foo() catch |err| switch (err) {};
2125 \\}
2126 \\
2127 );
2128}
2129
2130test "zig fmt: line comments in struct initializer" {
2131 try testCanonical(
2132 \\fn foo() void {
2133 \\ return Self{
2134 \\ .a = b,
2135 \\
2136 \\ // Initialize these two fields to buffer_size so that
2137 \\ // in `readFn` we treat the state as being able to read
2138 \\ .start_index = buffer_size,
2139 \\ .end_index = buffer_size,
2140 \\
2141 \\ // middle
2142 \\
2143 \\ .a = b,
2144 \\
2145 \\ // end
2146 \\ };
2147 \\}
2148 \\
2149 );
2150}
2151
2152test "zig fmt: first line comment in struct initializer" {
2120 try testCanonical(2153 try testCanonical(
2121 \\test "" {2154 \\pub fn acquire(self: *Self) HeldLock {
2122 \\ foo() catch |err| switch (err) {};2155 \\ return HeldLock{
2156 \\ // guaranteed allocation elision
2157 \\ .held = self.lock.acquire(),
2158 \\ .value = &self.private_data,
2159 \\ };
2123 \\}2160 \\}
2124 \\2161 \\
2125 );2162 );
2126}2163}
21272164
2128//test "zig fmt: line comments in struct initializer" {2165test "zig fmt: doc comments before struct field" {
2129// try testCanonical(2166 try testCanonical(
2130// \\fn foo() void {2167 \\pub const Allocator = struct {
2131// \\ return Self{2168 \\ /// Allocate byte_count bytes and return them in a slice, with the
2132// \\ .a = b,2169 \\ /// slice's pointer aligned at least to alignment bytes.
2133// \\2170 \\ allocFn: fn () void,
2134// \\ // Initialize these two fields to buffer_size so that2171 \\};
2135// \\ // in `readFn` we treat the state as being able to read2172 \\
2136// \\ .start_index = buffer_size,2173 );
2137// \\ .end_index = buffer_size,2174}
2138// \\
2139// \\ // middle
2140// \\
2141// \\ .a = b,
2142// \\
2143// \\ // end
2144// \\ };
2145// \\}
2146// \\
2147// );
2148//}
2149//
2150//test "zig fmt: first line comment in struct initializer" {
2151// try testCanonical(
2152// \\pub fn acquire(self: *Self) HeldLock {
2153// \\ return HeldLock{
2154// \\ // guaranteed allocation elision
2155// \\ .held = self.lock.acquire(),
2156// \\ .value = &self.private_data,
2157// \\ };
2158// \\}
2159// \\
2160// );
2161//}
2162//
2163//test "zig fmt: doc comments before struct field" {
2164// try testCanonical(
2165// \\pub const Allocator = struct {
2166// \\ /// Allocate byte_count bytes and return them in a slice, with the
2167// \\ /// slice's pointer aligned at least to alignment bytes.
2168// \\ allocFn: fn () void,
2169// \\};
2170// \\
2171// );
2172//}
21732175
2174// TODO: replace this with the next test case when possible
2175test "zig fmt: error set declaration" {2176test "zig fmt: error set declaration" {
2176 try testCanonical(2177 try testCanonical(
2177 \\const E = error{2178 \\const E = error{
...@@ -2180,58 +2181,30 @@ test "zig fmt: error set declaration" {...@@ -2180,58 +2181,30 @@ test "zig fmt: error set declaration" {
2180 \\2181 \\
2181 \\ C,2182 \\ C,
2182 \\};2183 \\};
2184 \\
2183 \\const Error = error{2185 \\const Error = error{
2184 \\ /// no more memory2186 \\ /// no more memory
2185 \\ OutOfMemory,2187 \\ OutOfMemory,
2186 \\};2188 \\};
2189 \\
2187 \\const Error = error{2190 \\const Error = error{
2188 \\ /// no more memory2191 \\ /// no more memory
2189 \\ OutOfMemory,2192 \\ OutOfMemory,
2190 \\2193 \\
2191 \\ /// another2194 \\ /// another
2192 \\ Another,2195 \\ Another,
2193 \\ /// and one more2196 \\
2194 \\ Another,2197 \\ // end
2195 \\};2198 \\};
2199 \\
2196 \\const Error = error{OutOfMemory};2200 \\const Error = error{OutOfMemory};
2197 \\const Error = error{};2201 \\const Error = error{};
2202 \\
2198 \\const Error = error{ OutOfMemory, OutOfTime };2203 \\const Error = error{ OutOfMemory, OutOfTime };
2199 \\2204 \\
2200 );2205 );
2201}2206}
22022207
2203//test "zig fmt: error set declaration" {
2204// try testCanonical(
2205// \\const E = error{
2206// \\ A,
2207// \\ B,
2208// \\
2209// \\ C,
2210// \\};
2211// \\
2212// \\const Error = error{
2213// \\ /// no more memory
2214// \\ OutOfMemory,
2215// \\};
2216// \\
2217// \\const Error = error{
2218// \\ /// no more memory
2219// \\ OutOfMemory,
2220// \\
2221// \\ /// another
2222// \\ Another,
2223// \\
2224// \\ // end
2225// \\};
2226// \\
2227// \\const Error = error{OutOfMemory};
2228// \\const Error = error{};
2229// \\
2230// \\const Error = error{ OutOfMemory, OutOfTime };
2231// \\
2232// );
2233//}
2234
2235test "zig fmt: union(enum(u32)) with assigned enum values" {2208test "zig fmt: union(enum(u32)) with assigned enum values" {
2236 try testCanonical(2209 try testCanonical(
2237 \\const MultipleChoice = union(enum(u32)) {2210 \\const MultipleChoice = union(enum(u32)) {
...@@ -2255,110 +2228,110 @@ test "zig fmt: resume from suspend block" {...@@ -2255,110 +2228,110 @@ test "zig fmt: resume from suspend block" {
2255 );2228 );
2256}2229}
22572230
2258//test "zig fmt: comments before error set decl" {2231test "zig fmt: comments before error set decl" {
2259// try testCanonical(2232 try testCanonical(
2260// \\const UnexpectedError = error{2233 \\const UnexpectedError = error{
2261// \\ /// The Operating System returned an undocumented error code.2234 \\ /// The Operating System returned an undocumented error code.
2262// \\ Unexpected,2235 \\ Unexpected,
2263// \\ // another2236 \\ // another
2264// \\ Another,2237 \\ Another,
2265// \\2238 \\
2266// \\ // in between2239 \\ // in between
2267// \\2240 \\
2268// \\ // at end2241 \\ // at end
2269// \\};2242 \\};
2270// \\2243 \\
2271// );2244 );
2272//}2245}
2273//2246
2274//test "zig fmt: comments before switch prong" {2247test "zig fmt: comments before switch prong" {
2275// try testCanonical(2248 try testCanonical(
2276// \\test "" {2249 \\test "" {
2277// \\ switch (err) {2250 \\ switch (err) {
2278// \\ error.PathAlreadyExists => continue,2251 \\ error.PathAlreadyExists => continue,
2279// \\2252 \\
2280// \\ // comment 12253 \\ // comment 1
2281// \\2254 \\
2282// \\ // comment 22255 \\ // comment 2
2283// \\ else => return err,2256 \\ else => return err,
2284// \\ // at end2257 \\ // at end
2285// \\ }2258 \\ }
2286// \\}2259 \\}
2287// \\2260 \\
2288// );2261 );
2289//}2262}
2290//2263
2291//test "zig fmt: comments before var decl in struct" {2264test "zig fmt: comments before var decl in struct" {
2292// try testCanonical(2265 try testCanonical(
2293// \\pub const vfs_cap_data = extern struct {2266 \\pub const vfs_cap_data = extern struct {
2294// \\ // All of these are mandated as little endian2267 \\ // All of these are mandated as little endian
2295// \\ // when on disk.2268 \\ // when on disk.
2296// \\ const Data = struct {2269 \\ const Data = struct {
2297// \\ permitted: u32,2270 \\ permitted: u32,
2298// \\ inheritable: u32,2271 \\ inheritable: u32,
2299// \\ };2272 \\ };
2300// \\2273 \\
2301// \\ // in between2274 \\ // in between
2302// \\2275 \\
2303// \\ /// All of these are mandated as little endian2276 \\ /// All of these are mandated as little endian
2304// \\ /// when on disk.2277 \\ /// when on disk.
2305// \\ const Data = struct {2278 \\ const Data = struct {
2306// \\ permitted: u32,2279 \\ permitted: u32,
2307// \\ inheritable: u32,2280 \\ inheritable: u32,
2308// \\ };2281 \\ };
2309// \\2282 \\
2310// \\ // at end2283 \\ // at end
2311// \\};2284 \\};
2312// \\2285 \\
2313// );2286 );
2314//}2287}
2315//2288
2316//test "zig fmt: array literal with 1 item on 1 line" {2289test "zig fmt: array literal with 1 item on 1 line" {
2317// try testCanonical(2290 try testCanonical(
2318// \\var s = []const u64{0} ** 25;2291 \\var s = []const u64{0} ** 25;
2319// \\2292 \\
2320// );2293 );
2321//}2294}
2322//2295
2323//test "zig fmt: comments before global variables" {2296test "zig fmt: comments before global variables" {
2324// try testCanonical(2297 try testCanonical(
2325// \\/// Foo copies keys and values before they go into the map, and2298 \\/// Foo copies keys and values before they go into the map, and
2326// \\/// frees them when they get removed.2299 \\/// frees them when they get removed.
2327// \\pub const Foo = struct {};2300 \\pub const Foo = struct {};
2328// \\2301 \\
2329// );2302 );
2330//}2303}
2331//2304
2332//test "zig fmt: comments in statements" {2305test "zig fmt: comments in statements" {
2333// try testCanonical(2306 try testCanonical(
2334// \\test "std" {2307 \\test "std" {
2335// \\ // statement comment2308 \\ // statement comment
2336// \\ _ = @import("foo/bar.zig");2309 \\ _ = @import("foo/bar.zig");
2337// \\2310 \\
2338// \\ // middle2311 \\ // middle
2339// \\ // middle22312 \\ // middle2
2340// \\2313 \\
2341// \\ // end2314 \\ // end
2342// \\}2315 \\}
2343// \\2316 \\
2344// );2317 );
2345//}2318}
2346//2319
2347//test "zig fmt: comments before test decl" {2320test "zig fmt: comments before test decl" {
2348// try testCanonical(2321 try testCanonical(
2349// \\/// top level doc comment2322 \\/// top level doc comment
2350// \\test "hi" {}2323 \\test "hi" {}
2351// \\2324 \\
2352// \\// top level normal comment2325 \\// top level normal comment
2353// \\test "hi" {}2326 \\test "hi" {}
2354// \\2327 \\
2355// \\// middle2328 \\// middle
2356// \\2329 \\
2357// \\// end2330 \\// end
2358// \\2331 \\
2359// );2332 );
2360//}2333}
2361//2334
2362//test "zig fmt: preserve spacing" {2335//test "zig fmt: preserve spacing" {
2363// try testCanonical(2336// try testCanonical(
2364// \\const std = @import("std");2337// \\const std = @import("std");
...@@ -2373,7 +2346,7 @@ test "zig fmt: resume from suspend block" {...@@ -2373,7 +2346,7 @@ test "zig fmt: resume from suspend block" {
2373// \\2346// \\
2374// );2347// );
2375//}2348//}
2376//2349
2377//test "zig fmt: return types" {2350//test "zig fmt: return types" {
2378// try testCanonical(2351// try testCanonical(
2379// \\pub fn main() !void {}2352// \\pub fn main() !void {}
...@@ -2798,43 +2771,43 @@ test "zig fmt: union declaration" {...@@ -2798,43 +2771,43 @@ test "zig fmt: union declaration" {
2798 );2771 );
2799}2772}
28002773
2801//test "zig fmt: arrays" {2774test "zig fmt: arrays" {
2802// try testCanonical(2775 try testCanonical(
2803// \\test "test array" {2776 \\test "test array" {
2804// \\ const a: [2]u8 = [2]u8{2777 \\ const a: [2]u8 = [2]u8{
2805// \\ 1,2778 \\ 1,
2806// \\ 2,2779 \\ 2,
2807// \\ };2780 \\ };
2808// \\ const a: [2]u8 = []u8{2781 \\ const a: [2]u8 = []u8{
2809// \\ 1,2782 \\ 1,
2810// \\ 2,2783 \\ 2,
2811// \\ };2784 \\ };
2812// \\ const a: [0]u8 = []u8{};2785 \\ const a: [0]u8 = []u8{};
2813// \\ const x: [4:0]u8 = undefined;2786 \\ const x: [4:0]u8 = undefined;
2814// \\}2787 \\}
2815// \\2788 \\
2816// );2789 );
2817//}2790}
28182791
2819//test "zig fmt: container initializers" {2792test "zig fmt: container initializers" {
2820// try testCanonical(2793 try testCanonical(
2821// \\const a0 = []u8{};2794 \\const a0 = []u8{};
2822// \\const a1 = []u8{1};2795 \\const a1 = []u8{1};
2823// \\const a2 = []u8{2796 \\const a2 = []u8{
2824// \\ 1,2797 \\ 1,
2825// \\ 2,2798 \\ 2,
2826// \\ 3,2799 \\ 3,
2827// \\ 4,2800 \\ 4,
2828// \\};2801 \\};
2829// \\const s0 = S{};2802 \\const s0 = S{};
2830// \\const s1 = S{ .a = 1 };2803 \\const s1 = S{ .a = 1 };
2831// \\const s2 = S{2804 \\const s2 = S{
2832// \\ .a = 1,2805 \\ .a = 1,
2833// \\ .b = 2,2806 \\ .b = 2,
2834// \\};2807 \\};
2835// \\2808 \\
2836// );2809 );
2837//}2810}
28382811
2839test "zig fmt: catch" {2812test "zig fmt: catch" {
2840 try testCanonical(2813 try testCanonical(
...@@ -3563,62 +3536,62 @@ test "zig fmt: integer literals with underscore separators" {...@@ -3563,62 +3536,62 @@ test "zig fmt: integer literals with underscore separators" {
3563 );3536 );
3564}3537}
35653538
3566//test "zig fmt: hex literals with underscore separators" {3539test "zig fmt: hex literals with underscore separators" {
3567// try testTransform(3540 try testTransform(
3568// \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {3541 \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
3569// \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;3542 \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
3570// \\ for (c [ 0_0 .. ]) |_, i| {3543 \\ for (c [ 0_0 .. ]) |_, i| {
3571// \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;3544 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
3572// \\ }3545 \\ }
3573// \\ return c;3546 \\ return c;
3574// \\}3547 \\}
3575// \\3548 \\
3576// \\3549 \\
3577// ,3550 ,
3578// \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {3551 \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
3579// \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;3552 \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
3580// \\ for (c[0_0..]) |_, i| {3553 \\ for (c[0_0..]) |_, i| {
3581// \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;3554 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
3582// \\ }3555 \\ }
3583// \\ return c;3556 \\ return c;
3584// \\}3557 \\}
3585// \\3558 \\
3586// );3559 );
3587//}3560}
35883561
3589//test "zig fmt: decimal float literals with underscore separators" {3562test "zig fmt: decimal float literals with underscore separators" {
3590// try testTransform(3563 try testTransform(
3591// \\pub fn main() void {3564 \\pub fn main() void {
3592// \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;3565 \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;
3593// \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;3566 \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;
3594// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3567 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3595// \\}3568 \\}
3596// ,3569 ,
3597// \\pub fn main() void {3570 \\pub fn main() void {
3598// \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;3571 \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;
3599// \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;3572 \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;
3600// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3573 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3601// \\}3574 \\}
3602// \\3575 \\
3603// );3576 );
3604//}3577}
36053578
3606//test "zig fmt: hexadeciaml float literals with underscore separators" {3579test "zig fmt: hexadeciaml float literals with underscore separators" {
3607// try testTransform(3580 try testTransform(
3608// \\pub fn main() void {3581 \\pub fn main() void {
3609// \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;3582 \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
3610// \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;3583 \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;
3611// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3584 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3612// \\}3585 \\}
3613// ,3586 ,
3614// \\pub fn main() void {3587 \\pub fn main() void {
3615// \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;3588 \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
3616// \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;3589 \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;
3617// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3590 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3618// \\}3591 \\}
3619// \\3592 \\
3620// );3593 );
3621//}3594}
36223595
3623//test "zig fmt: C var args" {3596//test "zig fmt: C var args" {
3624// try testCanonical(3597// try testCanonical(
lib/std/zig/render.zig+64-102
...@@ -37,66 +37,56 @@ pub fn render(gpa: *mem.Allocator, tree: ast.Tree) Error![]u8 {...@@ -37,66 +37,56 @@ pub fn render(gpa: *mem.Allocator, tree: ast.Tree) Error![]u8 {
37 return buffer.toOwnedSlice();37 return buffer.toOwnedSlice();
38}38}
3939
40/// Assumes there are no tokens in between start and end.40/// Assumes that start is the first byte past the previous token and
41fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize, prefix: []const u8) Error!usize {41/// that end is the last byte before the next token.
42fn renderCommentsAndNewlines(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!bool {
42 var index: usize = start;43 var index: usize = start;
43 var count: usize = 0;44 while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| {
44 while (true) {45 const comment_start = index + offset;
45 const comment_start = index +
46 (mem.indexOf(u8, tree.source[index..end], "//") orelse return count);
47 const newline = comment_start +46 const newline = comment_start +
48 mem.indexOfScalar(u8, tree.source[comment_start..end], '\n').?;47 mem.indexOfScalar(u8, tree.source[comment_start..end], '\n').?;
49 const untrimmed_comment = tree.source[comment_start..newline];48 const untrimmed_comment = tree.source[comment_start..newline];
50 const trimmed_comment = mem.trimRight(u8, untrimmed_comment, " \r\t");49 const trimmed_comment = mem.trimRight(u8, untrimmed_comment, " \r\t");
51 if (count == 0) {50
52 count += 1;51 // Leave up to one empty line before the comment
53 try ais.writer().writeAll(prefix);52 if (index == start and mem.containsAtLeast(u8, tree.source[index..comment_start], 2, "\n")) {
54 } else {53 try ais.insertNewline();
55 // If another newline occurs between prev comment and this one54 try ais.insertNewline();
56 // we honor it, but not any additional ones.55 } else if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) {
57 if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) {56 // Respect the newline directly before the comment. This allows an
58 try ais.insertNewline();57 // empty line between comments
59 }58 try ais.insertNewline();
59 } else if (index == start and start != 0) {
60 // If the comment is on the same line as the token before it,
61 // prefix it with a single space
62 try ais.writer().writeByte(' ');
60 }63 }
64
61 try ais.writer().print("{s}\n", .{trimmed_comment});65 try ais.writer().print("{s}\n", .{trimmed_comment});
62 index = newline + 1;66 index = newline + 1;
63 }67 }
68
69 // Leave up to one empty line if present in the source
70 if (index > start) index -= 1;
71 if (end != tree.source.len and mem.containsAtLeast(u8, tree.source[index..end], 2, "\n")) {
72 try ais.insertNewline();
73 }
74
75 return index != start;
64}76}
6577
66fn renderRoot(ais: *Ais, tree: ast.Tree) Error!void {78fn renderRoot(ais: *Ais, tree: ast.Tree) Error!void {
67 // Render all the line comments at the beginning of the file.79 // Render all the line comments at the beginning of the file.
68 const src_start: usize = if (mem.startsWith(u8, tree.source, "\xEF\xBB\xBF")) 3 else 0;80 const src_start: usize = if (mem.startsWith(u8, tree.source, "\xEF\xBB\xBF")) 3 else 0;
69 const comment_end_loc: usize = tree.tokens.items(.start)[0];81 const comment_end_loc: usize = tree.tokens.items(.start)[0];
70 _ = try renderComments(ais, tree, src_start, comment_end_loc, "");82 _ = try renderCommentsAndNewlines(ais, tree, src_start, comment_end_loc);
7183
72 // Root is always index 0.84 // Root is always index 0.
73 const nodes_data = tree.nodes.items(.data);85 const nodes_data = tree.nodes.items(.data);
74 const root_decls = tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs];86 const root_decls = tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs];
7587
76 return renderAllMembers(ais, tree, root_decls);88 for (root_decls) |decl| {
77}89 try renderMember(ais, tree, decl, .Newline);
78
79fn renderAllMembers(ais: *Ais, tree: ast.Tree, members: []const ast.Node.Index) Error!void {
80 if (members.len == 0) return;
81
82 const first_member = members[0];
83 try renderMember(ais, tree, first_member, .Newline);
84
85 for (members[1..]) |member| {
86 try renderExtraNewline(ais, tree, member);
87 try renderMember(ais, tree, member, .Newline);
88 }
89}
90
91fn renderExtraNewline(ais: *Ais, tree: ast.Tree, node: ast.Node.Index) Error!void {
92 return renderExtraNewlineToken(ais, tree, tree.firstToken(node));
93}
94
95fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, first_token: ast.TokenIndex) Error!void {
96 if (first_token == 0) return;
97 const token_starts = tree.tokens.items(.start);
98 if (tree.tokenLocation(token_starts[first_token - 1], first_token).line >= 2) {
99 return ais.insertNewline();
100 }90 }
101}91}
10292
...@@ -499,9 +489,11 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -499,9 +489,11 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
499 },489 },
500490
501 .GroupedExpression => {491 .GroupedExpression => {
502 try renderToken(ais, tree, main_tokens[node], .None);492 ais.pushIndentNextLine();
493 try renderToken(ais, tree, main_tokens[node], .None); // lparen
503 try renderExpression(ais, tree, datas[node].lhs, .None);494 try renderExpression(ais, tree, datas[node].lhs, .None);
504 return renderToken(ais, tree, datas[node].rhs, space);495 ais.popIndent();
496 return renderToken(ais, tree, datas[node].rhs, space); // rparen
505 },497 },
506498
507 .ContainerDecl,499 .ContainerDecl,
...@@ -552,7 +544,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -552,7 +544,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
552 ais.pushIndent();544 ais.pushIndent();
553 var i = lbrace + 1;545 var i = lbrace + 1;
554 while (i < rbrace) : (i += 1) {546 while (i < rbrace) : (i += 1) {
555 try renderExtraNewlineToken(ais, tree, i);
556 switch (token_tags[i]) {547 switch (token_tags[i]) {
557 .DocComment => try renderToken(ais, tree, i, .Newline),548 .DocComment => try renderToken(ais, tree, i, .Newline),
558 .Identifier => try renderToken(ais, tree, i, .Comma),549 .Identifier => try renderToken(ais, tree, i, .Comma),
...@@ -635,11 +626,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -635,11 +626,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
635 try renderToken(ais, tree, rparen + 1, .None); // lbrace626 try renderToken(ais, tree, rparen + 1, .None); // lbrace
636 return renderToken(ais, tree, rparen + 2, space); // rbrace627 return renderToken(ais, tree, rparen + 2, space); // rbrace
637 }628 }
629 ais.pushIndentNextLine();
638 try renderToken(ais, tree, rparen + 1, .Newline); // lbrace630 try renderToken(ais, tree, rparen + 1, .Newline); // lbrace
639 ais.pushIndent();631 for (cases) |case| {
640 try renderExpression(ais, tree, cases[0], .Comma);
641 for (cases[1..]) |case| {
642 try renderExtraNewline(ais, tree, case);
643 try renderExpression(ais, tree, case, .Comma);632 try renderExpression(ais, tree, case, .Comma);
644 }633 }
645 ais.popIndent();634 ais.popIndent();
...@@ -1469,9 +1458,7 @@ fn renderSwitchCase(...@@ -1469,9 +1458,7 @@ fn renderSwitchCase(
1469 try renderExpression(ais, tree, switch_case.ast.values[0], .Space);1458 try renderExpression(ais, tree, switch_case.ast.values[0], .Space);
1470 } else if (trailing_comma) {1459 } else if (trailing_comma) {
1471 // Render each value on a new line1460 // Render each value on a new line
1472 try renderExpression(ais, tree, switch_case.ast.values[0], .Comma);1461 for (switch_case.ast.values) |value_expr| {
1473 for (switch_case.ast.values[1..]) |value_expr| {
1474 try renderExtraNewline(ais, tree, value_expr);
1475 try renderExpression(ais, tree, value_expr, .Comma);1462 try renderExpression(ais, tree, value_expr, .Comma);
1476 }1463 }
1477 } else {1464 } else {
...@@ -1519,12 +1506,14 @@ fn renderBlock(...@@ -1519,12 +1506,14 @@ fn renderBlock(
1519 }1506 }
15201507
1521 if (statements.len == 0) {1508 if (statements.len == 0) {
1509 ais.pushIndentNextLine();
1522 try renderToken(ais, tree, lbrace, .None);1510 try renderToken(ais, tree, lbrace, .None);
1511 ais.popIndent();
1523 return renderToken(ais, tree, lbrace + 1, space); // rbrace1512 return renderToken(ais, tree, lbrace + 1, space); // rbrace
1524 }1513 }
15251514
1515 ais.pushIndentNextLine();
1526 try renderToken(ais, tree, lbrace, .Newline);1516 try renderToken(ais, tree, lbrace, .Newline);
1527 ais.pushIndent();
1528 for (statements) |stmt, i| {1517 for (statements) |stmt, i| {
1529 switch (node_tags[stmt]) {1518 switch (node_tags[stmt]) {
1530 .GlobalVarDecl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)),1519 .GlobalVarDecl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)),
...@@ -1533,9 +1522,6 @@ fn renderBlock(...@@ -1533,9 +1522,6 @@ fn renderBlock(
1533 .AlignedVarDecl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)),1522 .AlignedVarDecl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)),
1534 else => try renderExpression(ais, tree, stmt, .Semicolon),1523 else => try renderExpression(ais, tree, stmt, .Semicolon),
1535 }1524 }
1536 if (i + 1 < statements.len) {
1537 try renderExtraNewline(ais, tree, statements[i + 1]);
1538 }
1539 }1525 }
1540 ais.popIndent();1526 ais.popIndent();
15411527
...@@ -1566,18 +1552,14 @@ fn renderStructInit(...@@ -1566,18 +1552,14 @@ fn renderStructInit(
1566 ais.pushIndent();1552 ais.pushIndent();
1567 try renderToken(ais, tree, struct_init.ast.lbrace, .Newline);1553 try renderToken(ais, tree, struct_init.ast.lbrace, .Newline);
15681554
1569 try renderToken(ais, tree, struct_init.ast.lbrace + 1, .None); // .1555 for (struct_init.ast.fields) |field_init| {
1570 try renderToken(ais, tree, struct_init.ast.lbrace + 2, .Space); // name
1571 try renderToken(ais, tree, struct_init.ast.lbrace + 3, .Space); // =
1572 try renderExpression(ais, tree, struct_init.ast.fields[0], .Comma);
1573
1574 for (struct_init.ast.fields[1..]) |field_init| {
1575 const init_token = tree.firstToken(field_init);1556 const init_token = tree.firstToken(field_init);
1576 try renderToken(ais, tree, init_token - 3, .None); // .1557 try renderToken(ais, tree, init_token - 3, .None); // .
1577 try renderToken(ais, tree, init_token - 2, .Space); // name1558 try renderToken(ais, tree, init_token - 2, .Space); // name
1578 try renderToken(ais, tree, init_token - 1, .Space); // =1559 try renderToken(ais, tree, init_token - 1, .Space); // =
1579 try renderExpressionNewlined(ais, tree, field_init, .Comma);1560 try renderExpression(ais, tree, field_init, .Comma);
1580 }1561 }
1562
1581 ais.popIndent();1563 ais.popIndent();
1582 return renderToken(ais, tree, last_field_token + 2, space); // rbrace1564 return renderToken(ais, tree, last_field_token + 2, space); // rbrace
1583 } else {1565 } else {
...@@ -1620,9 +1602,8 @@ fn renderArrayInit(...@@ -1620,9 +1602,8 @@ fn renderArrayInit(
1620 ais.pushIndent();1602 ais.pushIndent();
1621 try renderToken(ais, tree, array_init.ast.lbrace, .Newline);1603 try renderToken(ais, tree, array_init.ast.lbrace, .Newline);
16221604
1623 try renderExpression(ais, tree, array_init.ast.elements[0], .Comma);1605 for (array_init.ast.elements) |elem| {
1624 for (array_init.ast.elements[1..]) |elem| {1606 try renderExpression(ais, tree, elem, .Comma);
1625 try renderExpressionNewlined(ais, tree, elem, .Comma);
1626 }1607 }
16271608
1628 ais.popIndent();1609 ais.popIndent();
...@@ -1693,7 +1674,7 @@ fn renderContainerDecl(...@@ -1693,7 +1674,7 @@ fn renderContainerDecl(
1693 const last_member_token = tree.lastToken(last_member);1674 const last_member_token = tree.lastToken(last_member);
1694 const rbrace = switch (token_tags[last_member_token + 1]) {1675 const rbrace = switch (token_tags[last_member_token + 1]) {
1695 .DocComment => last_member_token + 2,1676 .DocComment => last_member_token + 2,
1696 .Comma => switch (token_tags[last_member_token + 2]) {1677 .Comma, .Semicolon => switch (token_tags[last_member_token + 2]) {
1697 .DocComment => last_member_token + 3,1678 .DocComment => last_member_token + 3,
1698 .RBrace => last_member_token + 2,1679 .RBrace => last_member_token + 2,
1699 else => unreachable,1680 else => unreachable,
...@@ -1719,7 +1700,9 @@ fn renderContainerDecl(...@@ -1719,7 +1700,9 @@ fn renderContainerDecl(
1719 // One member per line.1700 // One member per line.
1720 ais.pushIndent();1701 ais.pushIndent();
1721 try renderToken(ais, tree, lbrace, .Newline); // lbrace1702 try renderToken(ais, tree, lbrace, .Newline); // lbrace
1722 try renderAllMembers(ais, tree, container_decl.ast.members);1703 for (container_decl.ast.members) |member| {
1704 try renderMember(ais, tree, member, .Newline);
1705 }
1723 ais.popIndent();1706 ais.popIndent();
17241707
1725 return renderToken(ais, tree, rbrace, space); // rbrace1708 return renderToken(ais, tree, rbrace, space); // rbrace
...@@ -1781,7 +1764,6 @@ fn renderAsm(...@@ -1781,7 +1764,6 @@ fn renderAsm(
17811764
1782 const comma = tree.firstToken(next_asm_output) - 1;1765 const comma = tree.firstToken(next_asm_output) - 1;
1783 try renderToken(ais, tree, comma, .Newline); // ,1766 try renderToken(ais, tree, comma, .Newline); // ,
1784 try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output));
1785 } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {1767 } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {
1786 try renderAsmOutput(ais, tree, asm_output, .Newline);1768 try renderAsmOutput(ais, tree, asm_output, .Newline);
1787 ais.popIndent();1769 ais.popIndent();
...@@ -1813,7 +1795,6 @@ fn renderAsm(...@@ -1813,7 +1795,6 @@ fn renderAsm(
18131795
1814 const first_token = tree.firstToken(next_asm_input);1796 const first_token = tree.firstToken(next_asm_input);
1815 try renderToken(ais, tree, first_token - 1, .Newline); // ,1797 try renderToken(ais, tree, first_token - 1, .Newline); // ,
1816 try renderExtraNewlineToken(ais, tree, first_token);
1817 } else if (asm_node.first_clobber == null) {1798 } else if (asm_node.first_clobber == null) {
1818 try renderAsmInput(ais, tree, asm_input, .Newline);1799 try renderAsmInput(ais, tree, asm_input, .Newline);
1819 ais.popIndent();1800 ais.popIndent();
...@@ -1894,8 +1875,6 @@ fn renderCall(...@@ -1894,8 +1875,6 @@ fn renderCall(
1894 try renderToken(ais, tree, comma, Space.Newline); // ,1875 try renderToken(ais, tree, comma, Space.Newline); // ,
18951876
1896 if (is_multiline_string) ais.pushIndent();1877 if (is_multiline_string) ais.pushIndent();
1897
1898 try renderExtraNewline(ais, tree, params[i + 1]);
1899 } else {1878 } else {
1900 try renderExpression(ais, tree, param_node, Space.Comma);1879 try renderExpression(ais, tree, param_node, Space.Comma);
1901 }1880 }
...@@ -1929,22 +1908,6 @@ fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space:...@@ -1929,22 +1908,6 @@ fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space:
1929 }1908 }
1930}1909}
19311910
1932/// Render an expression, but first insert an extra newline if the previous token is 2 or
1933/// more lines away.
1934fn renderExpressionNewlined(
1935 ais: *Ais,
1936 tree: ast.Tree,
1937 node: ast.Node.Index,
1938 space: Space,
1939) Error!void {
1940 const token_starts = tree.tokens.items(.start);
1941 const first_token = tree.firstToken(node);
1942 if (tree.tokenLocation(token_starts[first_token - 1], first_token).line >= 2) {
1943 try ais.insertNewline();
1944 }
1945 return renderExpression(ais, tree, node, space);
1946}
1947
1948fn renderTokenComma(ais: *Ais, tree: ast.Tree, token: ast.TokenIndex, space: Space) Error!void {1911fn renderTokenComma(ais: *Ais, tree: ast.Tree, token: ast.TokenIndex, space: Space) Error!void {
1949 const token_tags = tree.tokens.items(.tag);1912 const token_tags = tree.tokens.items(.tag);
1950 const maybe_comma = token + 1;1913 const maybe_comma = token + 1;
...@@ -1996,40 +1959,39 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp...@@ -1996,40 +1959,39 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp
19961959
1997 switch (space) {1960 switch (space) {
1998 .NoComment => {},1961 .NoComment => {},
1999 .None => {},1962 .None => _ = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]),
2000 .Comma => {1963 .Comma => {
2001 const count = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], ", ");1964 const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
2002 if (count == 0 and token_tags[token_index + 1] == .Comma) {1965 if (token_tags[token_index + 1] == .Comma) {
2003 return renderToken(ais, tree, token_index + 1, Space.Newline);1966 return renderToken(ais, tree, token_index + 1, .Newline);
2004 }1967 } else if (!comment) {
2005 try ais.writer().writeAll(",");1968 return ais.insertNewline();
2006
2007 if (token_tags[token_index + 2] != .MultilineStringLiteralLine) {
2008 try ais.insertNewline();
2009 }1969 }
2010 },1970 },
2011 .CommaSpace => {1971 .CommaSpace => {
2012 _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");1972 const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
2013 if (token_tags[token_index + 1] == .Comma) {1973 if (token_tags[token_index + 1] == .Comma) {
2014 return renderToken(ais, tree, token_index + 1, .Space);1974 return renderToken(ais, tree, token_index + 1, .Space);
2015 } else {1975 } else if (!comment) {
2016 return ais.writer().writeByte(' ');1976 return ais.writer().writeByte(' ');
2017 }1977 }
2018 },1978 },
2019 .Semicolon => {1979 .Semicolon => {
2020 _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");1980 const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
2021 if (token_tags[token_index + 1] == .Semicolon) {1981 if (token_tags[token_index + 1] == .Semicolon) {
2022 return renderToken(ais, tree, token_index + 1, .Newline);1982 return renderToken(ais, tree, token_index + 1, .Newline);
2023 } else {1983 } else if (!comment) {
2024 return ais.insertNewline();1984 return ais.insertNewline();
2025 }1985 }
2026 },1986 },
2027 .Space => {1987 .Space => {
2028 _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");1988 const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
2029 return ais.writer().writeByte(' ');1989 if (!comment) {
1990 return ais.writer().writeByte(' ');
1991 }
2030 },1992 },
2031 .Newline => {1993 .Newline => {
2032 if (token_tags[token_index + 1] != .MultilineStringLiteralLine) {1994 if (!try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1])) {
2033 try ais.insertNewline();1995 try ais.insertNewline();
2034 }1996 }
2035 },1997 },