aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/std/zig/parser_test.zig1083
-rw-r--r--lib/std/zig/render.zig166
2 files changed, 592 insertions, 657 deletions
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig
index c6ee4f6bd9..aad9ad3ed6 100644
--- a/lib/std/zig/parser_test.zig
+++ b/lib/std/zig/parser_test.zig
@@ -663,7 +663,9 @@ test "zig fmt: anon list literal 3 element comma" {
\\test {
\\ const x = .{
\\ a,
+ \\ // foo
\\ b,
+ \\
\\ c,
\\ };
\\}
@@ -874,20 +876,20 @@ test "zig fmt: enum literal" {
);
}
-//test "zig fmt: enum literal inside array literal" {
-// try testCanonical(
-// \\test "enums in arrays" {
-// \\ var colors = []Color{.Green};
-// \\ colors = []Colors{ .Green, .Cyan };
-// \\ colors = []Colors{
-// \\ .Grey,
-// \\ .Green,
-// \\ .Cyan,
-// \\ };
-// \\}
-// \\
-// );
-//}
+test "zig fmt: enum literal inside array literal" {
+ try testCanonical(
+ \\test "enums in arrays" {
+ \\ var colors = []Color{.Green};
+ \\ colors = []Colors{ .Green, .Cyan };
+ \\ colors = []Colors{
+ \\ .Grey,
+ \\ .Green,
+ \\ .Cyan,
+ \\ };
+ \\}
+ \\
+ );
+}
test "zig fmt: character literal larger than u8" {
try testCanonical(
@@ -954,56 +956,56 @@ test "zig fmt: linksection" {
// \\
// );
//}
-//
-//test "zig fmt: correctly space struct fields with doc comments" {
-// try testTransform(
-// \\pub const S = struct {
-// \\ /// A
-// \\ a: u8,
-// \\ /// B
-// \\ /// B (cont)
-// \\ b: u8,
-// \\
-// \\
-// \\ /// C
-// \\ c: u8,
-// \\};
-// \\
-// ,
-// \\pub const S = struct {
-// \\ /// A
-// \\ a: u8,
-// \\ /// B
-// \\ /// B (cont)
-// \\ b: u8,
-// \\
-// \\ /// C
-// \\ c: u8,
-// \\};
-// \\
-// );
-//}
-//
-//test "zig fmt: doc comments on param decl" {
-// try testCanonical(
-// \\pub const Allocator = struct {
-// \\ shrinkFn: fn (
-// \\ self: *Allocator,
-// \\ /// Guaranteed to be the same as what was returned from most recent call to
-// \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
-// \\ old_mem: []u8,
-// \\ /// Guaranteed to be the same as what was returned from most recent call to
-// \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
-// \\ old_alignment: u29,
-// \\ /// Guaranteed to be less than or equal to `old_mem.len`.
-// \\ new_byte_count: usize,
-// \\ /// Guaranteed to be less than or equal to `old_alignment`.
-// \\ new_alignment: u29,
-// \\ ) []u8,
-// \\};
-// \\
-// );
-//}
+
+test "zig fmt: correctly space struct fields with doc comments" {
+ try testTransform(
+ \\pub const S = struct {
+ \\ /// A
+ \\ a: u8,
+ \\ /// B
+ \\ /// B (cont)
+ \\ b: u8,
+ \\
+ \\
+ \\ /// C
+ \\ c: u8,
+ \\};
+ \\
+ ,
+ \\pub const S = struct {
+ \\ /// A
+ \\ a: u8,
+ \\ /// B
+ \\ /// B (cont)
+ \\ b: u8,
+ \\
+ \\ /// C
+ \\ c: u8,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: doc comments on param decl" {
+ try testCanonical(
+ \\pub const Allocator = struct {
+ \\ shrinkFn: fn (
+ \\ self: *Allocator,
+ \\ /// Guaranteed to be the same as what was returned from most recent call to
+ \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
+ \\ old_mem: []u8,
+ \\ /// Guaranteed to be the same as what was returned from most recent call to
+ \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
+ \\ old_alignment: u29,
+ \\ /// Guaranteed to be less than or equal to `old_mem.len`.
+ \\ new_byte_count: usize,
+ \\ /// Guaranteed to be less than or equal to `old_alignment`.
+ \\ new_alignment: u29,
+ \\ ) []u8,
+ \\};
+ \\
+ );
+}
test "zig fmt: aligned struct field" {
try testCanonical(
@@ -1142,13 +1144,13 @@ test "zig fmt: aligned struct field" {
// \\
// );
//}
-//
-//test "zig fmt: pointer of unknown length" {
-// try testCanonical(
-// \\fn foo(ptr: [*]u8) void {}
-// \\
-// );
-//}
+
+test "zig fmt: pointer of unknown length" {
+ try testCanonical(
+ \\fn foo(ptr: [*]u8) void {}
+ \\
+ );
+}
test "zig fmt: spaces around slice operator" {
try testCanonical(
@@ -1370,25 +1372,25 @@ test "zig fmt: async call in if condition" {
// \\
// );
//}
-//
-//test "zig fmt: if-else with comment before else" {
-// try testCanonical(
-// \\comptime {
-// \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
-// \\ if ((hx & 0x7fffffff) != 0x7f800000) {
-// \\ return Complex(f32).new(y - y, y - y);
-// \\ } // cexp(-inf +- i inf|nan) = 0 + i0
-// \\ else if (hx & 0x80000000 != 0) {
-// \\ return Complex(f32).new(0, 0);
-// \\ } // cexp(+inf +- i inf|nan) = inf + i nan
-// \\ else {
-// \\ return Complex(f32).new(x, y - y);
-// \\ }
-// \\}
-// \\
-// );
-//}
-//
+
+test "zig fmt: if-else with comment before else" {
+ try testCanonical(
+ \\comptime {
+ \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
+ \\ if ((hx & 0x7fffffff) != 0x7f800000) {
+ \\ return Complex(f32).new(y - y, y - y);
+ \\ } // cexp(-inf +- i inf|nan) = 0 + i0
+ \\ else if (hx & 0x80000000 != 0) {
+ \\ return Complex(f32).new(0, 0);
+ \\ } // cexp(+inf +- i inf|nan) = inf + i nan
+ \\ else {
+ \\ return Complex(f32).new(x, y - y);
+ \\ }
+ \\}
+ \\
+ );
+}
+
//test "zig fmt: if nested" {
// try testCanonical(
// \\pub fn foo() void {
@@ -1467,17 +1469,17 @@ test "zig fmt: enum decl with no trailing comma" {
);
}
-//test "zig fmt: switch comment before prong" {
-// try testCanonical(
-// \\comptime {
-// \\ switch (a) {
-// \\ // hi
-// \\ 0 => {},
-// \\ }
-// \\}
-// \\
-// );
-//}
+test "zig fmt: switch comment before prong" {
+ try testCanonical(
+ \\comptime {
+ \\ switch (a) {
+ \\ // hi
+ \\ 0 => {},
+ \\ }
+ \\}
+ \\
+ );
+}
test "zig fmt: struct literal no trailing comma" {
try testTransform(
@@ -1709,17 +1711,17 @@ test "zig fmt: multi line arguments without last comma" {
);
}
-//test "zig fmt: empty block with only comment" {
-// try testCanonical(
-// \\comptime {
-// \\ {
-// \\ // comment
-// \\ }
-// \\}
-// \\
-// );
-//}
-//
+test "zig fmt: empty block with only comment" {
+ try testCanonical(
+ \\comptime {
+ \\ {
+ \\ // comment
+ \\ }
+ \\}
+ \\
+ );
+}
+
//test "zig fmt: no trailing comma on struct decl" {
// try testCanonical(
// \\const RoundParam = struct {
@@ -1781,15 +1783,15 @@ test "zig fmt: extra newlines at the end" {
// \\
// );
//}
-//
-//test "zig fmt: nested struct literal with one item" {
-// try testCanonical(
-// \\const a = foo{
-// \\ .item = bar{ .a = b },
-// \\};
-// \\
-// );
-//}
+
+test "zig fmt: nested struct literal with one item" {
+ try testCanonical(
+ \\const a = foo{
+ \\ .item = bar{ .a = b },
+ \\};
+ \\
+ );
+}
test "zig fmt: switch cases trailing comma" {
try testTransform(
@@ -1848,26 +1850,26 @@ test "zig fmt: slice align" {
// \\
// );
//}
-//
-//test "zig fmt: first thing in file is line comment" {
-// try testCanonical(
-// \\// Introspection and determination of system libraries needed by zig.
-// \\
-// \\// Introspection and determination of system libraries needed by zig.
-// \\
-// \\const std = @import("std");
-// \\
-// );
-//}
-//
-//test "zig fmt: line comment after doc comment" {
-// try testCanonical(
-// \\/// doc comment
-// \\// line comment
-// \\fn foo() void {}
-// \\
-// );
-//}
+
+test "zig fmt: first thing in file is line comment" {
+ try testCanonical(
+ \\// Introspection and determination of system libraries needed by zig.
+ \\
+ \\// Introspection and determination of system libraries needed by zig.
+ \\
+ \\const std = @import("std");
+ \\
+ );
+}
+
+test "zig fmt: line comment after doc comment" {
+ try testCanonical(
+ \\/// doc comment
+ \\// line comment
+ \\fn foo() void {}
+ \\
+ );
+}
test "zig fmt: bit field alignment" {
try testCanonical(
@@ -1928,27 +1930,27 @@ test "zig fmt: nested blocks" {
);
}
-//test "zig fmt: block with same line comment after end brace" {
-// try testCanonical(
-// \\comptime {
-// \\ {
-// \\ b();
-// \\ } // comment
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: statements with comment between" {
-// try testCanonical(
-// \\comptime {
-// \\ a = b;
-// \\ // comment
-// \\ a = b;
-// \\}
-// \\
-// );
-//}
+test "zig fmt: block with same line comment after end brace" {
+ try testCanonical(
+ \\comptime {
+ \\ {
+ \\ b();
+ \\ } // comment
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: statements with comment between" {
+ try testCanonical(
+ \\comptime {
+ \\ a = b;
+ \\ // comment
+ \\ a = b;
+ \\}
+ \\
+ );
+}
test "zig fmt: statements with empty line between" {
try testCanonical(
@@ -1969,60 +1971,60 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {
);
}
-//test "zig fmt: comment after if before another if" {
-// try testCanonical(
-// \\test "aoeu" {
-// \\ // comment
-// \\ if (x) {
-// \\ bar();
-// \\ }
-// \\}
-// \\
-// \\test "aoeu" {
-// \\ if (x) {
-// \\ foo();
-// \\ }
-// \\ // comment
-// \\ if (x) {
-// \\ bar();
-// \\ }
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: line comment between if block and else keyword" {
-// try testCanonical(
-// \\test "aoeu" {
-// \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
-// \\ if ((hx & 0x7fffffff) != 0x7f800000) {
-// \\ return Complex(f32).new(y - y, y - y);
-// \\ }
-// \\ // cexp(-inf +- i inf|nan) = 0 + i0
-// \\ else if (hx & 0x80000000 != 0) {
-// \\ return Complex(f32).new(0, 0);
-// \\ }
-// \\ // cexp(+inf +- i inf|nan) = inf + i nan
-// \\ // another comment
-// \\ else {
-// \\ return Complex(f32).new(x, y - y);
-// \\ }
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: same line comments in expression" {
-// try testCanonical(
-// \\test "aoeu" {
-// \\ const x = ( // a
-// \\ 0 // b
-// \\ ); // c
-// \\}
-// \\
-// );
-//}
-//
+test "zig fmt: comment after if before another if" {
+ try testCanonical(
+ \\test "aoeu" {
+ \\ // comment
+ \\ if (x) {
+ \\ bar();
+ \\ }
+ \\}
+ \\
+ \\test "aoeu" {
+ \\ if (x) {
+ \\ foo();
+ \\ }
+ \\ // comment
+ \\ if (x) {
+ \\ bar();
+ \\ }
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: line comment between if block and else keyword" {
+ try testCanonical(
+ \\test "aoeu" {
+ \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
+ \\ if ((hx & 0x7fffffff) != 0x7f800000) {
+ \\ return Complex(f32).new(y - y, y - y);
+ \\ }
+ \\ // cexp(-inf +- i inf|nan) = 0 + i0
+ \\ else if (hx & 0x80000000 != 0) {
+ \\ return Complex(f32).new(0, 0);
+ \\ }
+ \\ // cexp(+inf +- i inf|nan) = inf + i nan
+ \\ // another comment
+ \\ else {
+ \\ return Complex(f32).new(x, y - y);
+ \\ }
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: same line comments in expression" {
+ try testCanonical(
+ \\test "aoeu" {
+ \\ const x = ( // a
+ \\ 0 // b
+ \\ ); // c
+ \\}
+ \\
+ );
+}
+
//test "zig fmt: add comma on last switch prong" {
// try testTransform(
// \\test "aoeu" {
@@ -2051,70 +2053,70 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {
// \\
// );
//}
-//
-//test "zig fmt: same-line comment after a statement" {
-// try testCanonical(
-// \\test "" {
-// \\ a = b;
-// \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
-// \\ a = b;
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: same-line comment after var decl in struct" {
-// try testCanonical(
-// \\pub const vfs_cap_data = extern struct {
-// \\ const Data = struct {}; // when on disk.
-// \\};
-// \\
-// );
-//}
-//
-//test "zig fmt: same-line comment after field decl" {
-// try testCanonical(
-// \\pub const dirent = extern struct {
-// \\ d_name: u8,
-// \\ d_name: u8, // comment 1
-// \\ d_name: u8,
-// \\ d_name: u8, // comment 2
-// \\ d_name: u8,
-// \\};
-// \\
-// );
-//}
-//
-//test "zig fmt: same-line comment after switch prong" {
-// try testCanonical(
-// \\test "" {
-// \\ switch (err) {
-// \\ error.PathAlreadyExists => {}, // comment 2
-// \\ else => return err, // comment 1
-// \\ }
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: same-line comment after non-block if expression" {
-// try testCanonical(
-// \\comptime {
-// \\ if (sr > n_uword_bits - 1) // d > r
-// \\ return 0;
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: same-line comment on comptime expression" {
-// try testCanonical(
-// \\test "" {
-// \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
-// \\}
-// \\
-// );
-//}
+
+test "zig fmt: same-line comment after a statement" {
+ try testCanonical(
+ \\test "" {
+ \\ a = b;
+ \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
+ \\ a = b;
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: same-line comment after var decl in struct" {
+ try testCanonical(
+ \\pub const vfs_cap_data = extern struct {
+ \\ const Data = struct {}; // when on disk.
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: same-line comment after field decl" {
+ try testCanonical(
+ \\pub const dirent = extern struct {
+ \\ d_name: u8,
+ \\ d_name: u8, // comment 1
+ \\ d_name: u8,
+ \\ d_name: u8, // comment 2
+ \\ d_name: u8,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: same-line comment after switch prong" {
+ try testCanonical(
+ \\test "" {
+ \\ switch (err) {
+ \\ error.PathAlreadyExists => {}, // comment 2
+ \\ else => return err, // comment 1
+ \\ }
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: same-line comment after non-block if expression" {
+ try testCanonical(
+ \\comptime {
+ \\ if (sr > n_uword_bits - 1) // d > r
+ \\ return 0;
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: same-line comment on comptime expression" {
+ try testCanonical(
+ \\test "" {
+ \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
+ \\}
+ \\
+ );
+}
test "zig fmt: switch with empty body" {
try testCanonical(
@@ -2125,53 +2127,52 @@ test "zig fmt: switch with empty body" {
);
}
-//test "zig fmt: line comments in struct initializer" {
-// try testCanonical(
-// \\fn foo() void {
-// \\ return Self{
-// \\ .a = b,
-// \\
-// \\ // Initialize these two fields to buffer_size so that
-// \\ // in `readFn` we treat the state as being able to read
-// \\ .start_index = buffer_size,
-// \\ .end_index = buffer_size,
-// \\
-// \\ // middle
-// \\
-// \\ .a = b,
-// \\
-// \\ // end
-// \\ };
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: first line comment in struct initializer" {
-// try testCanonical(
-// \\pub fn acquire(self: *Self) HeldLock {
-// \\ return HeldLock{
-// \\ // guaranteed allocation elision
-// \\ .held = self.lock.acquire(),
-// \\ .value = &self.private_data,
-// \\ };
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: doc comments before struct field" {
-// try testCanonical(
-// \\pub const Allocator = struct {
-// \\ /// Allocate byte_count bytes and return them in a slice, with the
-// \\ /// slice's pointer aligned at least to alignment bytes.
-// \\ allocFn: fn () void,
-// \\};
-// \\
-// );
-//}
+test "zig fmt: line comments in struct initializer" {
+ try testCanonical(
+ \\fn foo() void {
+ \\ return Self{
+ \\ .a = b,
+ \\
+ \\ // Initialize these two fields to buffer_size so that
+ \\ // in `readFn` we treat the state as being able to read
+ \\ .start_index = buffer_size,
+ \\ .end_index = buffer_size,
+ \\
+ \\ // middle
+ \\
+ \\ .a = b,
+ \\
+ \\ // end
+ \\ };
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: first line comment in struct initializer" {
+ try testCanonical(
+ \\pub fn acquire(self: *Self) HeldLock {
+ \\ return HeldLock{
+ \\ // guaranteed allocation elision
+ \\ .held = self.lock.acquire(),
+ \\ .value = &self.private_data,
+ \\ };
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: doc comments before struct field" {
+ try testCanonical(
+ \\pub const Allocator = struct {
+ \\ /// Allocate byte_count bytes and return them in a slice, with the
+ \\ /// slice's pointer aligned at least to alignment bytes.
+ \\ allocFn: fn () void,
+ \\};
+ \\
+ );
+}
-// TODO: replace this with the next test case when possible
test "zig fmt: error set declaration" {
try testCanonical(
\\const E = error{
@@ -2180,58 +2181,30 @@ test "zig fmt: error set declaration" {
\\
\\ C,
\\};
+ \\
\\const Error = error{
\\ /// no more memory
\\ OutOfMemory,
\\};
+ \\
\\const Error = error{
\\ /// no more memory
\\ OutOfMemory,
\\
\\ /// another
\\ Another,
- \\ /// and one more
- \\ Another,
+ \\
+ \\ // end
\\};
+ \\
\\const Error = error{OutOfMemory};
\\const Error = error{};
+ \\
\\const Error = error{ OutOfMemory, OutOfTime };
\\
);
}
-//test "zig fmt: error set declaration" {
-// try testCanonical(
-// \\const E = error{
-// \\ A,
-// \\ B,
-// \\
-// \\ C,
-// \\};
-// \\
-// \\const Error = error{
-// \\ /// no more memory
-// \\ OutOfMemory,
-// \\};
-// \\
-// \\const Error = error{
-// \\ /// no more memory
-// \\ OutOfMemory,
-// \\
-// \\ /// another
-// \\ Another,
-// \\
-// \\ // end
-// \\};
-// \\
-// \\const Error = error{OutOfMemory};
-// \\const Error = error{};
-// \\
-// \\const Error = error{ OutOfMemory, OutOfTime };
-// \\
-// );
-//}
-
test "zig fmt: union(enum(u32)) with assigned enum values" {
try testCanonical(
\\const MultipleChoice = union(enum(u32)) {
@@ -2255,110 +2228,110 @@ test "zig fmt: resume from suspend block" {
);
}
-//test "zig fmt: comments before error set decl" {
-// try testCanonical(
-// \\const UnexpectedError = error{
-// \\ /// The Operating System returned an undocumented error code.
-// \\ Unexpected,
-// \\ // another
-// \\ Another,
-// \\
-// \\ // in between
-// \\
-// \\ // at end
-// \\};
-// \\
-// );
-//}
-//
-//test "zig fmt: comments before switch prong" {
-// try testCanonical(
-// \\test "" {
-// \\ switch (err) {
-// \\ error.PathAlreadyExists => continue,
-// \\
-// \\ // comment 1
-// \\
-// \\ // comment 2
-// \\ else => return err,
-// \\ // at end
-// \\ }
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: comments before var decl in struct" {
-// try testCanonical(
-// \\pub const vfs_cap_data = extern struct {
-// \\ // All of these are mandated as little endian
-// \\ // when on disk.
-// \\ const Data = struct {
-// \\ permitted: u32,
-// \\ inheritable: u32,
-// \\ };
-// \\
-// \\ // in between
-// \\
-// \\ /// All of these are mandated as little endian
-// \\ /// when on disk.
-// \\ const Data = struct {
-// \\ permitted: u32,
-// \\ inheritable: u32,
-// \\ };
-// \\
-// \\ // at end
-// \\};
-// \\
-// );
-//}
-//
-//test "zig fmt: array literal with 1 item on 1 line" {
-// try testCanonical(
-// \\var s = []const u64{0} ** 25;
-// \\
-// );
-//}
-//
-//test "zig fmt: comments before global variables" {
-// try testCanonical(
-// \\/// Foo copies keys and values before they go into the map, and
-// \\/// frees them when they get removed.
-// \\pub const Foo = struct {};
-// \\
-// );
-//}
-//
-//test "zig fmt: comments in statements" {
-// try testCanonical(
-// \\test "std" {
-// \\ // statement comment
-// \\ _ = @import("foo/bar.zig");
-// \\
-// \\ // middle
-// \\ // middle2
-// \\
-// \\ // end
-// \\}
-// \\
-// );
-//}
-//
-//test "zig fmt: comments before test decl" {
-// try testCanonical(
-// \\/// top level doc comment
-// \\test "hi" {}
-// \\
-// \\// top level normal comment
-// \\test "hi" {}
-// \\
-// \\// middle
-// \\
-// \\// end
-// \\
-// );
-//}
-//
+test "zig fmt: comments before error set decl" {
+ try testCanonical(
+ \\const UnexpectedError = error{
+ \\ /// The Operating System returned an undocumented error code.
+ \\ Unexpected,
+ \\ // another
+ \\ Another,
+ \\
+ \\ // in between
+ \\
+ \\ // at end
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: comments before switch prong" {
+ try testCanonical(
+ \\test "" {
+ \\ switch (err) {
+ \\ error.PathAlreadyExists => continue,
+ \\
+ \\ // comment 1
+ \\
+ \\ // comment 2
+ \\ else => return err,
+ \\ // at end
+ \\ }
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: comments before var decl in struct" {
+ try testCanonical(
+ \\pub const vfs_cap_data = extern struct {
+ \\ // All of these are mandated as little endian
+ \\ // when on disk.
+ \\ const Data = struct {
+ \\ permitted: u32,
+ \\ inheritable: u32,
+ \\ };
+ \\
+ \\ // in between
+ \\
+ \\ /// All of these are mandated as little endian
+ \\ /// when on disk.
+ \\ const Data = struct {
+ \\ permitted: u32,
+ \\ inheritable: u32,
+ \\ };
+ \\
+ \\ // at end
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: array literal with 1 item on 1 line" {
+ try testCanonical(
+ \\var s = []const u64{0} ** 25;
+ \\
+ );
+}
+
+test "zig fmt: comments before global variables" {
+ try testCanonical(
+ \\/// Foo copies keys and values before they go into the map, and
+ \\/// frees them when they get removed.
+ \\pub const Foo = struct {};
+ \\
+ );
+}
+
+test "zig fmt: comments in statements" {
+ try testCanonical(
+ \\test "std" {
+ \\ // statement comment
+ \\ _ = @import("foo/bar.zig");
+ \\
+ \\ // middle
+ \\ // middle2
+ \\
+ \\ // end
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: comments before test decl" {
+ try testCanonical(
+ \\/// top level doc comment
+ \\test "hi" {}
+ \\
+ \\// top level normal comment
+ \\test "hi" {}
+ \\
+ \\// middle
+ \\
+ \\// end
+ \\
+ );
+}
+
//test "zig fmt: preserve spacing" {
// try testCanonical(
// \\const std = @import("std");
@@ -2373,7 +2346,7 @@ test "zig fmt: resume from suspend block" {
// \\
// );
//}
-//
+
//test "zig fmt: return types" {
// try testCanonical(
// \\pub fn main() !void {}
@@ -2798,43 +2771,43 @@ test "zig fmt: union declaration" {
);
}
-//test "zig fmt: arrays" {
-// try testCanonical(
-// \\test "test array" {
-// \\ const a: [2]u8 = [2]u8{
-// \\ 1,
-// \\ 2,
-// \\ };
-// \\ const a: [2]u8 = []u8{
-// \\ 1,
-// \\ 2,
-// \\ };
-// \\ const a: [0]u8 = []u8{};
-// \\ const x: [4:0]u8 = undefined;
-// \\}
-// \\
-// );
-//}
+test "zig fmt: arrays" {
+ try testCanonical(
+ \\test "test array" {
+ \\ const a: [2]u8 = [2]u8{
+ \\ 1,
+ \\ 2,
+ \\ };
+ \\ const a: [2]u8 = []u8{
+ \\ 1,
+ \\ 2,
+ \\ };
+ \\ const a: [0]u8 = []u8{};
+ \\ const x: [4:0]u8 = undefined;
+ \\}
+ \\
+ );
+}
-//test "zig fmt: container initializers" {
-// try testCanonical(
-// \\const a0 = []u8{};
-// \\const a1 = []u8{1};
-// \\const a2 = []u8{
-// \\ 1,
-// \\ 2,
-// \\ 3,
-// \\ 4,
-// \\};
-// \\const s0 = S{};
-// \\const s1 = S{ .a = 1 };
-// \\const s2 = S{
-// \\ .a = 1,
-// \\ .b = 2,
-// \\};
-// \\
-// );
-//}
+test "zig fmt: container initializers" {
+ try testCanonical(
+ \\const a0 = []u8{};
+ \\const a1 = []u8{1};
+ \\const a2 = []u8{
+ \\ 1,
+ \\ 2,
+ \\ 3,
+ \\ 4,
+ \\};
+ \\const s0 = S{};
+ \\const s1 = S{ .a = 1 };
+ \\const s2 = S{
+ \\ .a = 1,
+ \\ .b = 2,
+ \\};
+ \\
+ );
+}
test "zig fmt: catch" {
try testCanonical(
@@ -3563,62 +3536,62 @@ test "zig fmt: integer literals with underscore separators" {
);
}
-//test "zig fmt: hex literals with underscore separators" {
-// try testTransform(
-// \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
-// \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
-// \\ for (c [ 0_0 .. ]) |_, i| {
-// \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
-// \\ }
-// \\ return c;
-// \\}
-// \\
-// \\
-// ,
-// \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
-// \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
-// \\ for (c[0_0..]) |_, i| {
-// \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
-// \\ }
-// \\ return c;
-// \\}
-// \\
-// );
-//}
+test "zig fmt: hex literals with underscore separators" {
+ try testTransform(
+ \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
+ \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
+ \\ for (c [ 0_0 .. ]) |_, i| {
+ \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
+ \\ }
+ \\ return c;
+ \\}
+ \\
+ \\
+ ,
+ \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
+ \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
+ \\ for (c[0_0..]) |_, i| {
+ \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
+ \\ }
+ \\ return c;
+ \\}
+ \\
+ );
+}
-//test "zig fmt: decimal float literals with underscore separators" {
-// try testTransform(
-// \\pub fn main() void {
-// \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;
-// \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;
-// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
-// \\}
-// ,
-// \\pub fn main() void {
-// \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;
-// \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;
-// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
-// \\}
-// \\
-// );
-//}
+test "zig fmt: decimal float literals with underscore separators" {
+ try testTransform(
+ \\pub fn main() void {
+ \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;
+ \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;
+ \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
+ \\}
+ ,
+ \\pub fn main() void {
+ \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;
+ \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;
+ \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
+ \\}
+ \\
+ );
+}
-//test "zig fmt: hexadeciaml float literals with underscore separators" {
-// try testTransform(
-// \\pub fn main() void {
-// \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
-// \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;
-// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
-// \\}
-// ,
-// \\pub fn main() void {
-// \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
-// \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;
-// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
-// \\}
-// \\
-// );
-//}
+test "zig fmt: hexadeciaml float literals with underscore separators" {
+ try testTransform(
+ \\pub fn main() void {
+ \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
+ \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;
+ \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
+ \\}
+ ,
+ \\pub fn main() void {
+ \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
+ \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;
+ \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
+ \\}
+ \\
+ );
+}
//test "zig fmt: C var args" {
// try testCanonical(
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index 051b3f46b1..4ffbaeff19 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -37,66 +37,56 @@ pub fn render(gpa: *mem.Allocator, tree: ast.Tree) Error![]u8 {
return buffer.toOwnedSlice();
}
-/// Assumes there are no tokens in between start and end.
-fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize, prefix: []const u8) Error!usize {
+/// Assumes that start is the first byte past the previous token and
+/// that end is the last byte before the next token.
+fn renderCommentsAndNewlines(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!bool {
var index: usize = start;
- var count: usize = 0;
- while (true) {
- const comment_start = index +
- (mem.indexOf(u8, tree.source[index..end], "//") orelse return count);
+ while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| {
+ const comment_start = index + offset;
const newline = comment_start +
mem.indexOfScalar(u8, tree.source[comment_start..end], '\n').?;
const untrimmed_comment = tree.source[comment_start..newline];
const trimmed_comment = mem.trimRight(u8, untrimmed_comment, " \r\t");
- if (count == 0) {
- count += 1;
- try ais.writer().writeAll(prefix);
- } else {
- // If another newline occurs between prev comment and this one
- // we honor it, but not any additional ones.
- if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) {
- try ais.insertNewline();
- }
+
+ // Leave up to one empty line before the comment
+ if (index == start and mem.containsAtLeast(u8, tree.source[index..comment_start], 2, "\n")) {
+ try ais.insertNewline();
+ try ais.insertNewline();
+ } else if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) {
+ // Respect the newline directly before the comment. This allows an
+ // empty line between comments
+ try ais.insertNewline();
+ } else if (index == start and start != 0) {
+ // If the comment is on the same line as the token before it,
+ // prefix it with a single space
+ try ais.writer().writeByte(' ');
}
+
try ais.writer().print("{s}\n", .{trimmed_comment});
index = newline + 1;
}
+
+ // Leave up to one empty line if present in the source
+ if (index > start) index -= 1;
+ if (end != tree.source.len and mem.containsAtLeast(u8, tree.source[index..end], 2, "\n")) {
+ try ais.insertNewline();
+ }
+
+ return index != start;
}
fn renderRoot(ais: *Ais, tree: ast.Tree) Error!void {
// Render all the line comments at the beginning of the file.
const src_start: usize = if (mem.startsWith(u8, tree.source, "\xEF\xBB\xBF")) 3 else 0;
const comment_end_loc: usize = tree.tokens.items(.start)[0];
- _ = try renderComments(ais, tree, src_start, comment_end_loc, "");
+ _ = try renderCommentsAndNewlines(ais, tree, src_start, comment_end_loc);
// Root is always index 0.
const nodes_data = tree.nodes.items(.data);
const root_decls = tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs];
- return renderAllMembers(ais, tree, root_decls);
-}
-
-fn renderAllMembers(ais: *Ais, tree: ast.Tree, members: []const ast.Node.Index) Error!void {
- if (members.len == 0) return;
-
- const first_member = members[0];
- try renderMember(ais, tree, first_member, .Newline);
-
- for (members[1..]) |member| {
- try renderExtraNewline(ais, tree, member);
- try renderMember(ais, tree, member, .Newline);
- }
-}
-
-fn renderExtraNewline(ais: *Ais, tree: ast.Tree, node: ast.Node.Index) Error!void {
- return renderExtraNewlineToken(ais, tree, tree.firstToken(node));
-}
-
-fn renderExtraNewlineToken(ais: *Ais, tree: ast.Tree, first_token: ast.TokenIndex) Error!void {
- if (first_token == 0) return;
- const token_starts = tree.tokens.items(.start);
- if (tree.tokenLocation(token_starts[first_token - 1], first_token).line >= 2) {
- return ais.insertNewline();
+ for (root_decls) |decl| {
+ try renderMember(ais, tree, decl, .Newline);
}
}
@@ -499,9 +489,11 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
},
.GroupedExpression => {
- try renderToken(ais, tree, main_tokens[node], .None);
+ ais.pushIndentNextLine();
+ try renderToken(ais, tree, main_tokens[node], .None); // lparen
try renderExpression(ais, tree, datas[node].lhs, .None);
- return renderToken(ais, tree, datas[node].rhs, space);
+ ais.popIndent();
+ return renderToken(ais, tree, datas[node].rhs, space); // rparen
},
.ContainerDecl,
@@ -552,7 +544,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
ais.pushIndent();
var i = lbrace + 1;
while (i < rbrace) : (i += 1) {
- try renderExtraNewlineToken(ais, tree, i);
switch (token_tags[i]) {
.DocComment => try renderToken(ais, tree, i, .Newline),
.Identifier => try renderToken(ais, tree, i, .Comma),
@@ -635,11 +626,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
try renderToken(ais, tree, rparen + 1, .None); // lbrace
return renderToken(ais, tree, rparen + 2, space); // rbrace
}
+ ais.pushIndentNextLine();
try renderToken(ais, tree, rparen + 1, .Newline); // lbrace
- ais.pushIndent();
- try renderExpression(ais, tree, cases[0], .Comma);
- for (cases[1..]) |case| {
- try renderExtraNewline(ais, tree, case);
+ for (cases) |case| {
try renderExpression(ais, tree, case, .Comma);
}
ais.popIndent();
@@ -1469,9 +1458,7 @@ fn renderSwitchCase(
try renderExpression(ais, tree, switch_case.ast.values[0], .Space);
} else if (trailing_comma) {
// Render each value on a new line
- try renderExpression(ais, tree, switch_case.ast.values[0], .Comma);
- for (switch_case.ast.values[1..]) |value_expr| {
- try renderExtraNewline(ais, tree, value_expr);
+ for (switch_case.ast.values) |value_expr| {
try renderExpression(ais, tree, value_expr, .Comma);
}
} else {
@@ -1519,12 +1506,14 @@ fn renderBlock(
}
if (statements.len == 0) {
+ ais.pushIndentNextLine();
try renderToken(ais, tree, lbrace, .None);
+ ais.popIndent();
return renderToken(ais, tree, lbrace + 1, space); // rbrace
}
+ ais.pushIndentNextLine();
try renderToken(ais, tree, lbrace, .Newline);
- ais.pushIndent();
for (statements) |stmt, i| {
switch (node_tags[stmt]) {
.GlobalVarDecl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)),
@@ -1533,9 +1522,6 @@ fn renderBlock(
.AlignedVarDecl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)),
else => try renderExpression(ais, tree, stmt, .Semicolon),
}
- if (i + 1 < statements.len) {
- try renderExtraNewline(ais, tree, statements[i + 1]);
- }
}
ais.popIndent();
@@ -1566,18 +1552,14 @@ fn renderStructInit(
ais.pushIndent();
try renderToken(ais, tree, struct_init.ast.lbrace, .Newline);
- try renderToken(ais, tree, struct_init.ast.lbrace + 1, .None); // .
- try renderToken(ais, tree, struct_init.ast.lbrace + 2, .Space); // name
- try renderToken(ais, tree, struct_init.ast.lbrace + 3, .Space); // =
- try renderExpression(ais, tree, struct_init.ast.fields[0], .Comma);
-
- for (struct_init.ast.fields[1..]) |field_init| {
+ for (struct_init.ast.fields) |field_init| {
const init_token = tree.firstToken(field_init);
try renderToken(ais, tree, init_token - 3, .None); // .
try renderToken(ais, tree, init_token - 2, .Space); // name
try renderToken(ais, tree, init_token - 1, .Space); // =
- try renderExpressionNewlined(ais, tree, field_init, .Comma);
+ try renderExpression(ais, tree, field_init, .Comma);
}
+
ais.popIndent();
return renderToken(ais, tree, last_field_token + 2, space); // rbrace
} else {
@@ -1620,9 +1602,8 @@ fn renderArrayInit(
ais.pushIndent();
try renderToken(ais, tree, array_init.ast.lbrace, .Newline);
- try renderExpression(ais, tree, array_init.ast.elements[0], .Comma);
- for (array_init.ast.elements[1..]) |elem| {
- try renderExpressionNewlined(ais, tree, elem, .Comma);
+ for (array_init.ast.elements) |elem| {
+ try renderExpression(ais, tree, elem, .Comma);
}
ais.popIndent();
@@ -1693,7 +1674,7 @@ fn renderContainerDecl(
const last_member_token = tree.lastToken(last_member);
const rbrace = switch (token_tags[last_member_token + 1]) {
.DocComment => last_member_token + 2,
- .Comma => switch (token_tags[last_member_token + 2]) {
+ .Comma, .Semicolon => switch (token_tags[last_member_token + 2]) {
.DocComment => last_member_token + 3,
.RBrace => last_member_token + 2,
else => unreachable,
@@ -1719,7 +1700,9 @@ fn renderContainerDecl(
// One member per line.
ais.pushIndent();
try renderToken(ais, tree, lbrace, .Newline); // lbrace
- try renderAllMembers(ais, tree, container_decl.ast.members);
+ for (container_decl.ast.members) |member| {
+ try renderMember(ais, tree, member, .Newline);
+ }
ais.popIndent();
return renderToken(ais, tree, rbrace, space); // rbrace
@@ -1781,7 +1764,6 @@ fn renderAsm(
const comma = tree.firstToken(next_asm_output) - 1;
try renderToken(ais, tree, comma, .Newline); // ,
- try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output));
} else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {
try renderAsmOutput(ais, tree, asm_output, .Newline);
ais.popIndent();
@@ -1813,7 +1795,6 @@ fn renderAsm(
const first_token = tree.firstToken(next_asm_input);
try renderToken(ais, tree, first_token - 1, .Newline); // ,
- try renderExtraNewlineToken(ais, tree, first_token);
} else if (asm_node.first_clobber == null) {
try renderAsmInput(ais, tree, asm_input, .Newline);
ais.popIndent();
@@ -1894,8 +1875,6 @@ fn renderCall(
try renderToken(ais, tree, comma, Space.Newline); // ,
if (is_multiline_string) ais.pushIndent();
-
- try renderExtraNewline(ais, tree, params[i + 1]);
} else {
try renderExpression(ais, tree, param_node, Space.Comma);
}
@@ -1929,22 +1908,6 @@ fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space:
}
}
-/// Render an expression, but first insert an extra newline if the previous token is 2 or
-/// more lines away.
-fn renderExpressionNewlined(
- ais: *Ais,
- tree: ast.Tree,
- node: ast.Node.Index,
- space: Space,
-) Error!void {
- const token_starts = tree.tokens.items(.start);
- const first_token = tree.firstToken(node);
- if (tree.tokenLocation(token_starts[first_token - 1], first_token).line >= 2) {
- try ais.insertNewline();
- }
- return renderExpression(ais, tree, node, space);
-}
-
fn renderTokenComma(ais: *Ais, tree: ast.Tree, token: ast.TokenIndex, space: Space) Error!void {
const token_tags = tree.tokens.items(.tag);
const maybe_comma = token + 1;
@@ -1996,40 +1959,39 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp
switch (space) {
.NoComment => {},
- .None => {},
+ .None => _ = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]),
.Comma => {
- const count = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], ", ");
- if (count == 0 and token_tags[token_index + 1] == .Comma) {
- return renderToken(ais, tree, token_index + 1, Space.Newline);
- }
- try ais.writer().writeAll(",");
-
- if (token_tags[token_index + 2] != .MultilineStringLiteralLine) {
- try ais.insertNewline();
+ const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
+ if (token_tags[token_index + 1] == .Comma) {
+ return renderToken(ais, tree, token_index + 1, .Newline);
+ } else if (!comment) {
+ return ais.insertNewline();
}
},
.CommaSpace => {
- _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");
+ const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
if (token_tags[token_index + 1] == .Comma) {
return renderToken(ais, tree, token_index + 1, .Space);
- } else {
+ } else if (!comment) {
return ais.writer().writeByte(' ');
}
},
.Semicolon => {
- _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");
+ const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
if (token_tags[token_index + 1] == .Semicolon) {
return renderToken(ais, tree, token_index + 1, .Newline);
- } else {
+ } else if (!comment) {
return ais.insertNewline();
}
},
.Space => {
- _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");
- return ais.writer().writeByte(' ');
+ const comment = try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]);
+ if (!comment) {
+ return ais.writer().writeByte(' ');
+ }
},
.Newline => {
- if (token_tags[token_index + 1] != .MultilineStringLiteralLine) {
+ if (!try renderCommentsAndNewlines(ais, tree, token_start + lexeme.len, token_starts[token_index + 1])) {
try ais.insertNewline();
}
},