aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-02-01 17:23:49 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-02-01 17:23:49 -0700
commit20554d32c0a9e8adeb311645797e0d6873f4bbc0 (patch)
tree1080a2c4700156e8b1283ddbadad64e1f4520063 /lib/std
parentbf8fafc37d4182196d108c773ae36c33a109d703 (diff)
downloadzig-20554d32c0a9e8adeb311645797e0d6873f4bbc0.tar.gz
zig-20554d32c0a9e8adeb311645797e0d6873f4bbc0.zip
zig fmt: start reworking with new memory layout
* start implementation of ast.Tree.firstToken and lastToken * clarify some ast.Node doc comments * reimplement renderToken
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/zig/ast.zig300
-rw-r--r--lib/std/zig/parse.zig2
-rw-r--r--lib/std/zig/parser_test.zig7425
-rw-r--r--lib/std/zig/render.zig4443
-rw-r--r--lib/std/zig/tokenizer.zig31
5 files changed, 6121 insertions, 6080 deletions
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index 823e0312cd..3fd34cd03c 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -185,24 +185,293 @@ pub const Tree = struct {
}
}
- /// Skips over comments.
- pub fn prevToken(self: *const Tree, token_index: TokenIndex) TokenIndex {
- const token_tags = self.tokens.items(.tag);
- var index = token_index - 1;
- while (token_tags[index] == .LineComment) {
- index -= 1;
+ pub fn firstToken(tree: Tree, node: Node.Index) TokenIndex {
+ const tags = tree.nodes.items(.tag);
+ const datas = tree.nodes.items(.data);
+ const main_tokens = tree.nodes.items(.main_token);
+ switch (tags[node]) {
+ .Root => return 0,
+
+ .UsingNamespace,
+ .TestDecl,
+ .ErrDefer,
+ .Defer,
+ .BoolNot,
+ .Negation,
+ .BitNot,
+ .NegationWrap,
+ .AddressOf,
+ .Try,
+ .Await,
+ .OptionalType,
+ .ArrayInitDotTwo,
+ .ArrayInitDot,
+ .StructInitDotTwo,
+ .StructInitDot,
+ .Switch,
+ .IfSimple,
+ .IfSimpleOptional,
+ .If,
+ .IfOptional,
+ .IfError,
+ .Suspend,
+ .Resume,
+ .Continue,
+ .Break,
+ .Return,
+ .AnyFrameType,
+ .OneToken,
+ .Identifier,
+ .EnumLiteral,
+ .MultilineStringLiteral,
+ .GroupedExpression,
+ .BuiltinCallTwo,
+ .BuiltinCall,
+ .ErrorSetDecl,
+ .AnyType,
+ .Comptime,
+ .Nosuspend,
+ .Block,
+ .AsmSimple,
+ .Asm,
+ => return main_tokens[node],
+
+ .Catch,
+ .FieldAccess,
+ .UnwrapOptional,
+ .EqualEqual,
+ .BangEqual,
+ .LessThan,
+ .GreaterThan,
+ .LessOrEqual,
+ .GreaterOrEqual,
+ .AssignMul,
+ .AssignDiv,
+ .AssignMod,
+ .AssignAdd,
+ .AssignSub,
+ .AssignBitShiftLeft,
+ .AssignBitShiftRight,
+ .AssignBitAnd,
+ .AssignBitXor,
+ .AssignBitOr,
+ .AssignMulWrap,
+ .AssignAddWrap,
+ .AssignSubWrap,
+ .Assign,
+ .MergeErrorSets,
+ .Mul,
+ .Div,
+ .Mod,
+ .ArrayMult,
+ .MulWrap,
+ .Add,
+ .Sub,
+ .ArrayCat,
+ .AddWrap,
+ .SubWrap,
+ .BitShiftLeft,
+ .BitShiftRight,
+ .BitAnd,
+ .BitXor,
+ .BitOr,
+ .OrElse,
+ .BoolAnd,
+ .BoolOr,
+ .SliceOpen,
+ .Slice,
+ .Deref,
+ .ArrayAccess,
+ .ArrayInitOne,
+ .ArrayInit,
+ .StructInitOne,
+ .CallOne,
+ .Call,
+ .SwitchCaseOne,
+ .SwitchRange,
+ .FnDecl,
+ => return tree.firstToken(datas[node].lhs),
+
+ .GlobalVarDecl,
+ .LocalVarDecl,
+ .SimpleVarDecl,
+ .AlignedVarDecl,
+ .ArrayType,
+ .ArrayTypeSentinel,
+ .PtrTypeAligned,
+ .PtrTypeSentinel,
+ .PtrType,
+ .SliceType,
+ .StructInit,
+ .SwitchCaseMulti,
+ .WhileSimple,
+ .WhileSimpleOptional,
+ .WhileCont,
+ .WhileContOptional,
+ .While,
+ .WhileOptional,
+ .WhileError,
+ .ForSimple,
+ .For,
+ .FnProtoSimple,
+ .FnProtoSimpleMulti,
+ .FnProtoOne,
+ .FnProto,
+ .ContainerDecl,
+ .ContainerDeclArg,
+ .TaggedUnion,
+ .TaggedUnionEnumTag,
+ .ContainerFieldInit,
+ .ContainerFieldAlign,
+ .ContainerField,
+ .AsmOutput,
+ .AsmInput,
+ .ErrorValue,
+ .ErrorUnion,
+ => @panic("TODO finish implementing firstToken"),
}
- return index;
}
- /// Skips over comments.
- pub fn nextToken(self: *const Tree, token_index: TokenIndex) TokenIndex {
- const token_tags = self.tokens.items(.tag);
- var index = token_index + 1;
- while (token_tags[index] == .LineComment) {
- index += 1;
+ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex {
+ const tags = tree.nodes.items(.tag);
+ const datas = tree.nodes.items(.data);
+ const main_tokens = tree.nodes.items(.main_token);
+ switch (tags[node]) {
+ .Root,
+ .UsingNamespace,
+ .TestDecl,
+ .ErrDefer,
+ .Defer,
+ .BoolNot,
+ .Negation,
+ .BitNot,
+ .NegationWrap,
+ .AddressOf,
+ .Try,
+ .Await,
+ .OptionalType,
+ .ArrayInitDotTwo,
+ .ArrayInitDot,
+ .StructInitDotTwo,
+ .StructInitDot,
+ .Switch,
+ .IfSimple,
+ .IfSimpleOptional,
+ .If,
+ .IfOptional,
+ .IfError,
+ .Suspend,
+ .Resume,
+ .Continue,
+ .Break,
+ .Return,
+ .AnyFrameType,
+ .OneToken,
+ .Identifier,
+ .EnumLiteral,
+ .MultilineStringLiteral,
+ .GroupedExpression,
+ .BuiltinCallTwo,
+ .BuiltinCall,
+ .ErrorSetDecl,
+ .AnyType,
+ .Comptime,
+ .Nosuspend,
+ .Block,
+ .AsmSimple,
+ .Asm,
+ .Catch,
+ .FieldAccess,
+ .UnwrapOptional,
+ .EqualEqual,
+ .BangEqual,
+ .LessThan,
+ .GreaterThan,
+ .LessOrEqual,
+ .GreaterOrEqual,
+ .AssignMul,
+ .AssignDiv,
+ .AssignMod,
+ .AssignAdd,
+ .AssignSub,
+ .AssignBitShiftLeft,
+ .AssignBitShiftRight,
+ .AssignBitAnd,
+ .AssignBitXor,
+ .AssignBitOr,
+ .AssignMulWrap,
+ .AssignAddWrap,
+ .AssignSubWrap,
+ .Assign,
+ .MergeErrorSets,
+ .Mul,
+ .Div,
+ .Mod,
+ .ArrayMult,
+ .MulWrap,
+ .Add,
+ .Sub,
+ .ArrayCat,
+ .AddWrap,
+ .SubWrap,
+ .BitShiftLeft,
+ .BitShiftRight,
+ .BitAnd,
+ .BitXor,
+ .BitOr,
+ .OrElse,
+ .BoolAnd,
+ .BoolOr,
+ .SliceOpen,
+ .Slice,
+ .Deref,
+ .ArrayAccess,
+ .ArrayInitOne,
+ .ArrayInit,
+ .StructInitOne,
+ .CallOne,
+ .Call,
+ .SwitchCaseOne,
+ .SwitchRange,
+ .FnDecl,
+ .GlobalVarDecl,
+ .LocalVarDecl,
+ .SimpleVarDecl,
+ .AlignedVarDecl,
+ .ArrayType,
+ .ArrayTypeSentinel,
+ .PtrTypeAligned,
+ .PtrTypeSentinel,
+ .PtrType,
+ .SliceType,
+ .StructInit,
+ .SwitchCaseMulti,
+ .WhileSimple,
+ .WhileSimpleOptional,
+ .WhileCont,
+ .WhileContOptional,
+ .While,
+ .WhileOptional,
+ .WhileError,
+ .ForSimple,
+ .For,
+ .FnProtoSimple,
+ .FnProtoSimpleMulti,
+ .FnProtoOne,
+ .FnProto,
+ .ContainerDecl,
+ .ContainerDeclArg,
+ .TaggedUnion,
+ .TaggedUnionEnumTag,
+ .ContainerFieldInit,
+ .ContainerFieldAlign,
+ .ContainerField,
+ .AsmOutput,
+ .AsmInput,
+ .ErrorValue,
+ .ErrorUnion,
+ => @panic("TODO finish implementing lastToken"),
}
- return index;
}
};
@@ -454,7 +723,7 @@ pub const Node = struct {
/// lhs is test name token (must be string literal), if any.
/// rhs is the body node.
TestDecl,
- /// lhs is the index into global_var_decl_list.
+ /// lhs is the index into extra_data.
/// rhs is the initialization expression, if any.
GlobalVarDecl,
/// `var a: x align(y) = rhs`
@@ -732,6 +1001,7 @@ pub const Node = struct {
/// `nosuspend lhs`. rhs unused.
Nosuspend,
/// `{}`. `sub_list[lhs..rhs]`.
+ /// main_token points at the `{`.
Block,
/// `asm(lhs)`. rhs unused.
AsmSimple,
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig
index 04c44f5c9c..05efea7fe1 100644
--- a/lib/std/zig/parse.zig
+++ b/lib/std/zig/parse.zig
@@ -594,7 +594,7 @@ const Parser = struct {
p.eatToken(.Keyword_var) orelse
return null_node;
- const name_token = try p.expectToken(.Identifier);
+ _ = try p.expectToken(.Identifier);
const type_node: Node.Index = if (p.eatToken(.Colon) == null) 0 else try p.expectTypeExpr();
const align_node = try p.parseByteAlign();
const section_node = try p.parseLinkSection();
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig
index 279402d71b..d4a01da0d0 100644
--- a/lib/std/zig/parser_test.zig
+++ b/lib/std/zig/parser_test.zig
@@ -3,3727 +3,3704 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
-test "zig fmt: convert var to anytype" {
- // TODO remove in next release cycle
- try testTransform(
- \\pub fn main(
- \\ a: var,
- \\ bar: var,
- \\) void {}
- ,
- \\pub fn main(
- \\ a: anytype,
- \\ bar: anytype,
- \\) void {}
- \\
- );
-}
-
-test "zig fmt: noasync to nosuspend" {
- // TODO: remove this
- try testTransform(
- \\pub fn main() void {
- \\ noasync call();
- \\}
- ,
- \\pub fn main() void {
- \\ nosuspend call();
- \\}
- \\
- );
-}
-
-test "recovery: top level" {
- try testError(
- \\test "" {inline}
- \\test "" {inline}
- , &[_]Error{
- .ExpectedInlinable,
- .ExpectedInlinable,
- });
-}
-
-test "recovery: block statements" {
- try testError(
- \\test "" {
- \\ foo + +;
- \\ inline;
- \\}
- , &[_]Error{
- .InvalidToken,
- .ExpectedInlinable,
- });
-}
-
-test "recovery: missing comma" {
- try testError(
- \\test "" {
- \\ switch (foo) {
- \\ 2 => {}
- \\ 3 => {}
- \\ else => {
- \\ foo && bar +;
- \\ }
- \\ }
- \\}
- , &[_]Error{
- .ExpectedToken,
- .ExpectedToken,
- .InvalidAnd,
- .InvalidToken,
- });
-}
-
-test "recovery: extra qualifier" {
- try testError(
- \\const a: *const const u8;
- \\test ""
- , &[_]Error{
- .ExtraConstQualifier,
- .ExpectedLBrace,
- });
-}
-
-test "recovery: missing return type" {
- try testError(
- \\fn foo() {
- \\ a && b;
- \\}
- \\test ""
- , &[_]Error{
- .ExpectedReturnType,
- .InvalidAnd,
- .ExpectedLBrace,
- });
-}
-
-test "recovery: continue after invalid decl" {
- try testError(
- \\fn foo {
- \\ inline;
- \\}
- \\pub test "" {
- \\ async a && b;
- \\}
- , &[_]Error{
- .ExpectedToken,
- .ExpectedPubItem,
- .ExpectedParamList,
- .InvalidAnd,
- });
- try testError(
- \\threadlocal test "" {
- \\ @a && b;
- \\}
- , &[_]Error{
- .ExpectedVarDecl,
- .ExpectedParamList,
- .InvalidAnd,
- });
-}
-
-test "recovery: invalid extern/inline" {
- try testError(
- \\inline test "" { a && b; }
- , &[_]Error{
- .ExpectedFn,
- .InvalidAnd,
- });
- try testError(
- \\extern "" test "" { a && b; }
- , &[_]Error{
- .ExpectedVarDeclOrFn,
- .InvalidAnd,
- });
-}
-
-test "recovery: missing semicolon" {
- try testError(
- \\test "" {
- \\ comptime a && b
- \\ c && d
- \\ @foo
- \\}
- , &[_]Error{
- .InvalidAnd,
- .ExpectedToken,
- .InvalidAnd,
- .ExpectedToken,
- .ExpectedParamList,
- .ExpectedToken,
- });
-}
-
-test "recovery: invalid container members" {
- try testError(
- \\usingnamespace;
- \\foo+
- \\bar@,
- \\while (a == 2) { test "" {}}
- \\test "" {
- \\ a && b
- \\}
- , &[_]Error{
- .ExpectedExpr,
- .ExpectedToken,
- .ExpectedToken,
- .ExpectedContainerMembers,
- .InvalidAnd,
- .ExpectedToken,
- });
-}
-
-test "recovery: invalid parameter" {
- try testError(
- \\fn main() void {
- \\ a(comptime T: type)
- \\}
- , &[_]Error{
- .ExpectedToken,
- });
-}
-
-test "recovery: extra '}' at top level" {
- try testError(
- \\}}}
- \\test "" {
- \\ a && b;
- \\}
- , &[_]Error{
- .ExpectedContainerMembers,
- .ExpectedContainerMembers,
- .ExpectedContainerMembers,
- .InvalidAnd,
- });
-}
-
-test "recovery: mismatched bracket at top level" {
- try testError(
- \\const S = struct {
- \\ arr: 128]?G
- \\};
- , &[_]Error{
- .ExpectedToken,
- });
-}
-
-test "recovery: invalid global error set access" {
- try testError(
- \\test "" {
- \\ error && foo;
- \\}
- , &[_]Error{
- .ExpectedToken,
- .ExpectedIdentifier,
- .InvalidAnd,
- });
-}
-
-test "recovery: invalid asterisk after pointer dereference" {
- try testError(
- \\test "" {
- \\ var sequence = "repeat".*** 10;
- \\}
- , &[_]Error{
- .AsteriskAfterPointerDereference,
- });
- try testError(
- \\test "" {
- \\ var sequence = "repeat".** 10&&a;
- \\}
- , &[_]Error{
- .AsteriskAfterPointerDereference,
- .InvalidAnd,
- });
-}
-
-test "recovery: missing semicolon after if, for, while stmt" {
- try testError(
- \\test "" {
- \\ if (foo) bar
- \\ for (foo) |a| bar
- \\ while (foo) bar
- \\ a && b;
- \\}
- , &[_]Error{
- .ExpectedSemiOrElse,
- .ExpectedSemiOrElse,
- .ExpectedSemiOrElse,
- .InvalidAnd,
- });
-}
-
-test "recovery: invalid comptime" {
- try testError(
- \\comptime
- , &[_]Error{
- .ExpectedBlockOrField,
- });
-}
-
-test "recovery: missing block after for/while loops" {
- try testError(
- \\test "" { while (foo) }
- , &[_]Error{
- .ExpectedBlockOrAssignment,
- });
- try testError(
- \\test "" { for (foo) |bar| }
- , &[_]Error{
- .ExpectedBlockOrAssignment,
- });
-}
-
-test "zig fmt: respect line breaks after var declarations" {
- try testCanonical(
- \\const crc =
- \\ lookup_tables[0][p[7]] ^
- \\ lookup_tables[1][p[6]] ^
- \\ lookup_tables[2][p[5]] ^
- \\ lookup_tables[3][p[4]] ^
- \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
- \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
- \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
- \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
- \\
- );
-}
-
-test "zig fmt: multiline string mixed with comments" {
- try testCanonical(
- \\const s1 =
- \\ //\\one
- \\ \\two)
- \\ \\three
- \\;
- \\const s2 =
- \\ \\one
- \\ \\two)
- \\ //\\three
- \\;
- \\const s3 =
- \\ \\one
- \\ //\\two)
- \\ \\three
- \\;
- \\const s4 =
- \\ \\one
- \\ //\\two
- \\ \\three
- \\ //\\four
- \\ \\five
- \\;
- \\const a =
- \\ 1;
- \\
- );
-}
-
-test "zig fmt: empty file" {
- try testCanonical(
- \\
- );
-}
-
-test "zig fmt: if statment" {
- try testCanonical(
- \\test "" {
- \\ if (optional()) |some|
- \\ bar = some.foo();
- \\}
- \\
- );
-}
-
-test "zig fmt: top-level fields" {
- try testCanonical(
- \\a: did_you_know,
- \\b: all_files_are,
- \\structs: ?x,
- \\
- );
-}
-
-test "zig fmt: decl between fields" {
- try testError(
- \\const S = struct {
- \\ const foo = 2;
- \\ const bar = 2;
- \\ const baz = 2;
- \\ a: usize,
- \\ const foo1 = 2;
- \\ const bar1 = 2;
- \\ const baz1 = 2;
- \\ b: usize,
- \\};
- , &[_]Error{
- .DeclBetweenFields,
- });
-}
-
-test "zig fmt: eof after missing comma" {
- try testError(
- \\foo()
- , &[_]Error{
- .ExpectedToken,
- });
-}
-
-test "zig fmt: errdefer with payload" {
- try testCanonical(
- \\pub fn main() anyerror!void {
- \\ errdefer |a| x += 1;
- \\ errdefer |a| {}
- \\ errdefer |a| {
- \\ x += 1;
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: nosuspend block" {
- try testCanonical(
- \\pub fn main() anyerror!void {
- \\ nosuspend {
- \\ var foo: Foo = .{ .bar = 42 };
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: nosuspend await" {
- try testCanonical(
- \\fn foo() void {
- \\ x = nosuspend await y;
- \\}
- \\
- );
-}
-
-test "zig fmt: trailing comma in container declaration" {
- try testCanonical(
- \\const X = struct { foo: i32 };
- \\const X = struct { foo: i32, bar: i32 };
- \\const X = struct { foo: i32 = 1, bar: i32 = 2 };
- \\const X = struct { foo: i32 align(4), bar: i32 align(4) };
- \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };
- \\
- );
- try testCanonical(
- \\test "" {
- \\ comptime {
- \\ const X = struct {
- \\ x: i32
- \\ };
- \\ }
- \\}
- \\
- );
- try testTransform(
- \\const X = struct {
- \\ foo: i32, bar: i8 };
- ,
- \\const X = struct {
- \\ foo: i32, bar: i8
- \\};
- \\
- );
-}
-
-test "zig fmt: trailing comma in fn parameter list" {
- try testCanonical(
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) i32 {}
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) align(8) i32 {}
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) linksection(".text") i32 {}
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) callconv(.C) i32 {}
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) align(8) linksection(".text") i32 {}
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) align(8) callconv(.C) i32 {}
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) align(8) linksection(".text") callconv(.C) i32 {}
- \\pub fn f(
- \\ a: i32,
- \\ b: i32,
- \\) linksection(".text") callconv(.C) i32 {}
- \\
- );
-}
-
-test "zig fmt: comptime struct field" {
- try testCanonical(
- \\const Foo = struct {
- \\ a: i32,
- \\ comptime b: i32 = 1234,
- \\};
- \\
- );
-}
-
-test "zig fmt: c pointer type" {
- try testCanonical(
- \\pub extern fn repro() [*c]const u8;
- \\
- );
-}
-
-test "zig fmt: builtin call with trailing comma" {
- try testCanonical(
- \\pub fn main() void {
- \\ @breakpoint();
- \\ _ = @boolToInt(a);
- \\ _ = @call(
- \\ a,
- \\ b,
- \\ c,
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: asm expression with comptime content" {
- try testCanonical(
- \\comptime {
- \\ asm ("foo" ++ "bar");
- \\}
- \\pub fn main() void {
- \\ asm volatile ("foo" ++ "bar");
- \\ asm volatile ("foo" ++ "bar"
- \\ : [_] "" (x)
- \\ );
- \\ asm volatile ("foo" ++ "bar"
- \\ : [_] "" (x)
- \\ : [_] "" (y)
- \\ );
- \\ asm volatile ("foo" ++ "bar"
- \\ : [_] "" (x)
- \\ : [_] "" (y)
- \\ : "h", "e", "l", "l", "o"
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: anytype struct field" {
- try testCanonical(
- \\pub const Pointer = struct {
- \\ sentinel: anytype,
- \\};
- \\
- );
-}
-
-test "zig fmt: sentinel-terminated array type" {
- try testCanonical(
- \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
- \\ return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
- \\}
- \\
- );
-}
-
-test "zig fmt: sentinel-terminated slice type" {
- try testCanonical(
- \\pub fn toSlice(self: Buffer) [:0]u8 {
- \\ return self.list.toSlice()[0..self.len()];
- \\}
- \\
- );
-}
-
-test "zig fmt: anon literal in array" {
- try testCanonical(
- \\var arr: [2]Foo = .{
- \\ .{ .a = 2 },
- \\ .{ .b = 3 },
- \\};
- \\
- );
-}
-
-test "zig fmt: alignment in anonymous literal" {
- try testTransform(
- \\const a = .{
- \\ "U", "L", "F",
- \\ "U'",
- \\ "L'",
- \\ "F'",
- \\};
- \\
- ,
- \\const a = .{
- \\ "U", "L", "F",
- \\ "U'", "L'", "F'",
- \\};
- \\
- );
-}
-
-test "zig fmt: anon struct literal syntax" {
- try testCanonical(
- \\const x = .{
- \\ .a = b,
- \\ .c = d,
- \\};
- \\
- );
-}
-
-test "zig fmt: anon list literal syntax" {
- try testCanonical(
- \\const x = .{ a, b, c };
- \\
- );
-}
-
-test "zig fmt: async function" {
- try testCanonical(
- \\pub const Server = struct {
- \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void,
- \\};
- \\test "hi" {
- \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
- \\}
- \\
- );
-}
-
-test "zig fmt: whitespace fixes" {
- try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",
- \\test "" {
- \\ const hi = x;
- \\}
- \\// zig fmt: off
- \\test ""{
- \\ const a = b;}
- \\
- );
-}
-
-test "zig fmt: while else err prong with no block" {
- try testCanonical(
- \\test "" {
- \\ const result = while (returnError()) |value| {
- \\ break value;
- \\ } else |err| @as(i32, 2);
- \\ expect(result == 2);
- \\}
- \\
- );
-}
-
-test "zig fmt: tagged union with enum values" {
- try testCanonical(
- \\const MultipleChoice2 = union(enum(u32)) {
- \\ Unspecified1: i32,
- \\ A: f32 = 20,
- \\ Unspecified2: void,
- \\ B: bool = 40,
- \\ Unspecified3: i32,
- \\ C: i8 = 60,
- \\ Unspecified4: void,
- \\ D: void = 1000,
- \\ Unspecified5: i32,
- \\};
- \\
- );
-}
-
-test "zig fmt: allowzero pointer" {
- try testCanonical(
- \\const T = [*]allowzero const u8;
- \\
- );
-}
-
-test "zig fmt: enum literal" {
- try testCanonical(
- \\const x = .hi;
- \\
- );
-}
-
-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(
- \\const x = '\u{01f4a9}';
- \\
- );
-}
-
-test "zig fmt: infix operator and then multiline string literal" {
- try testCanonical(
- \\const x = "" ++
- \\ \\ hi
- \\;
- \\
- );
-}
-
-test "zig fmt: infix operator and then multiline string literal" {
- try testCanonical(
- \\const x = "" ++
- \\ \\ hi0
- \\ \\ hi1
- \\ \\ hi2
- \\;
- \\
- );
-}
-
-test "zig fmt: C pointers" {
- try testCanonical(
- \\const Ptr = [*c]i32;
- \\
- );
-}
-
-test "zig fmt: threadlocal" {
- try testCanonical(
- \\threadlocal var x: i32 = 1234;
- \\
- );
-}
-
-test "zig fmt: linksection" {
- try testCanonical(
- \\export var aoeu: u64 linksection(".text.derp") = 1234;
- \\export fn _start() linksection(".text.boot") callconv(.Naked) noreturn {}
- \\
- );
-}
-
-test "zig fmt: correctly move doc comments on struct fields" {
- try testTransform(
- \\pub const section_64 = extern struct {
- \\ sectname: [16]u8, /// name of this section
- \\ segname: [16]u8, /// segment this section goes in
- \\};
- ,
- \\pub const section_64 = extern struct {
- \\ /// name of this section
- \\ sectname: [16]u8,
- \\ /// segment this section goes in
- \\ segname: [16]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(
- \\pub const S = struct {
- \\ f: i32 align(32),
- \\};
- \\
- );
- try testCanonical(
- \\pub const S = struct {
- \\ f: i32 align(32) = 1,
- \\};
- \\
- );
-}
-
-test "zig fmt: comment to disable/enable zig fmt first" {
- try testCanonical(
- \\// Test trailing comma syntax
- \\// zig fmt: off
- \\
- \\const struct_trailing_comma = struct { x: i32, y: i32, };
- );
-}
-
-test "zig fmt: comment to disable/enable zig fmt" {
- try testTransform(
- \\const a = b;
- \\// zig fmt: off
- \\const c = d;
- \\// zig fmt: on
- \\const e = f;
- ,
- \\const a = b;
- \\// zig fmt: off
- \\const c = d;
- \\// zig fmt: on
- \\const e = f;
- \\
- );
-}
-
-test "zig fmt: line comment following 'zig fmt: off'" {
- try testCanonical(
- \\// zig fmt: off
- \\// Test
- \\const e = f;
- );
-}
-
-test "zig fmt: doc comment following 'zig fmt: off'" {
- try testCanonical(
- \\// zig fmt: off
- \\/// test
- \\const e = f;
- );
-}
-
-test "zig fmt: line and doc comment following 'zig fmt: off'" {
- try testCanonical(
- \\// zig fmt: off
- \\// test 1
- \\/// test 2
- \\const e = f;
- );
-}
-
-test "zig fmt: doc and line comment following 'zig fmt: off'" {
- try testCanonical(
- \\// zig fmt: off
- \\/// test 1
- \\// test 2
- \\const e = f;
- );
-}
-
-test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
- try testCanonical(
- \\// zig fmt: off
- \\// zig fmt: on
- \\// zig fmt: off
- \\const e = f;
- \\// zig fmt: off
- \\// zig fmt: on
- \\// zig fmt: off
- \\const a = b;
- \\// zig fmt: on
- \\const c = d;
- \\// zig fmt: on
- \\
- );
-}
-
-test "zig fmt: line comment following 'zig fmt: on'" {
- try testCanonical(
- \\// zig fmt: off
- \\const e = f;
- \\// zig fmt: on
- \\// test
- \\const e = f;
- \\
- );
-}
-
-test "zig fmt: doc comment following 'zig fmt: on'" {
- try testCanonical(
- \\// zig fmt: off
- \\const e = f;
- \\// zig fmt: on
- \\/// test
- \\const e = f;
- \\
- );
-}
-
-test "zig fmt: line and doc comment following 'zig fmt: on'" {
- try testCanonical(
- \\// zig fmt: off
- \\const e = f;
- \\// zig fmt: on
- \\// test1
- \\/// test2
- \\const e = f;
- \\
- );
-}
-
-test "zig fmt: doc and line comment following 'zig fmt: on'" {
- try testCanonical(
- \\// zig fmt: off
- \\const e = f;
- \\// zig fmt: on
- \\/// test1
- \\// test2
- \\const e = f;
- \\
- );
-}
-
-test "zig fmt: pointer of unknown length" {
- try testCanonical(
- \\fn foo(ptr: [*]u8) void {}
- \\
- );
-}
-
-test "zig fmt: spaces around slice operator" {
- try testCanonical(
- \\var a = b[c..d];
- \\var a = b[c..d :0];
- \\var a = b[c + 1 .. d];
- \\var a = b[c + 1 ..];
- \\var a = b[c .. d + 1];
- \\var a = b[c .. d + 1 :0];
- \\var a = b[c.a..d.e];
- \\var a = b[c.a..d.e :0];
- \\
- );
-}
-
-test "zig fmt: async call in if condition" {
- try testCanonical(
- \\comptime {
- \\ if (async b()) {
- \\ a();
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: 2nd arg multiline string" {
- try testCanonical(
- \\comptime {
- \\ cases.addAsm("hello world linux x86_64",
- \\ \\.text
- \\ , "Hello, world!\n");
- \\}
- \\
- );
-}
-
-test "zig fmt: 2nd arg multiline string many args" {
- try testCanonical(
- \\comptime {
- \\ cases.addAsm("hello world linux x86_64",
- \\ \\.text
- \\ , "Hello, world!\n", "Hello, world!\n");
- \\}
- \\
- );
-}
-
-test "zig fmt: final arg multiline string" {
- try testCanonical(
- \\comptime {
- \\ cases.addAsm("hello world linux x86_64", "Hello, world!\n",
- \\ \\.text
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: if condition wraps" {
- try testTransform(
- \\comptime {
- \\ if (cond and
- \\ cond) {
- \\ return x;
- \\ }
- \\ while (cond and
- \\ cond) {
- \\ return x;
- \\ }
- \\ if (a == b and
- \\ c) {
- \\ a = b;
- \\ }
- \\ while (a == b and
- \\ c) {
- \\ a = b;
- \\ }
- \\ if ((cond and
- \\ cond)) {
- \\ return x;
- \\ }
- \\ while ((cond and
- \\ cond)) {
- \\ return x;
- \\ }
- \\ var a = if (a) |*f| x: {
- \\ break :x &a.b;
- \\ } else |err| err;
- \\ var a = if (cond and
- \\ cond) |*f|
- \\ x: {
- \\ break :x &a.b;
- \\ } else |err| err;
- \\}
- ,
- \\comptime {
- \\ if (cond and
- \\ cond)
- \\ {
- \\ return x;
- \\ }
- \\ while (cond and
- \\ cond)
- \\ {
- \\ return x;
- \\ }
- \\ if (a == b and
- \\ c)
- \\ {
- \\ a = b;
- \\ }
- \\ while (a == b and
- \\ c)
- \\ {
- \\ a = b;
- \\ }
- \\ if ((cond and
- \\ cond))
- \\ {
- \\ return x;
- \\ }
- \\ while ((cond and
- \\ cond))
- \\ {
- \\ return x;
- \\ }
- \\ var a = if (a) |*f| x: {
- \\ break :x &a.b;
- \\ } else |err| err;
- \\ var a = if (cond and
- \\ cond) |*f|
- \\ x: {
- \\ break :x &a.b;
- \\ } else |err| err;
- \\}
- \\
- );
-}
-
-test "zig fmt: if condition has line break but must not wrap" {
- try testCanonical(
- \\comptime {
- \\ if (self.user_input_options.put(
- \\ name,
- \\ UserInputOption{
- \\ .name = name,
- \\ .used = false,
- \\ },
- \\ ) catch unreachable) |*prev_value| {
- \\ foo();
- \\ bar();
- \\ }
- \\ if (put(
- \\ a,
- \\ b,
- \\ )) {
- \\ foo();
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: if condition has line break but must not wrap" {
- try testCanonical(
- \\comptime {
- \\ if (self.user_input_options.put(name, UserInputOption{
- \\ .name = name,
- \\ .used = false,
- \\ }) catch unreachable) |*prev_value| {
- \\ foo();
- \\ bar();
- \\ }
- \\ if (put(
- \\ a,
- \\ b,
- \\ )) {
- \\ foo();
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: function call with multiline argument" {
- try testCanonical(
- \\comptime {
- \\ self.user_input_options.put(name, UserInputOption{
- \\ .name = name,
- \\ .used = false,
- \\ });
- \\}
- \\
- );
-}
-
-test "zig fmt: same-line doc comment on variable declaration" {
- try testTransform(
- \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
- \\pub const MAP_FILE = 0x0000; /// map from file (default)
- \\
- \\pub const EMEDIUMTYPE = 124; /// Wrong medium type
- \\
- \\// nameserver query return codes
- \\pub const ENSROK = 0; /// DNS server returned answer with no data
- ,
- \\/// allocated from memory, swap space
- \\pub const MAP_ANONYMOUS = 0x1000;
- \\/// map from file (default)
- \\pub const MAP_FILE = 0x0000;
- \\
- \\/// Wrong medium type
- \\pub const EMEDIUMTYPE = 124;
- \\
- \\// nameserver query return codes
- \\/// DNS server returned answer with no data
- \\pub const ENSROK = 0;
- \\
- );
-}
-
-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 {
- \\ return if ((aInt & bInt) >= 0)
- \\ if (aInt < bInt)
- \\ GE_LESS
- \\ else if (aInt == bInt)
- \\ GE_EQUAL
- \\ else
- \\ GE_GREATER
- \\ else if (aInt > bInt)
- \\ GE_LESS
- \\ else if (aInt == bInt)
- \\ GE_EQUAL
- \\ else
- \\ GE_GREATER;
- \\}
- \\
- );
-}
-
-test "zig fmt: respect line breaks in if-else" {
- try testCanonical(
- \\comptime {
- \\ return if (cond) a else b;
- \\ return if (cond)
- \\ a
- \\ else
- \\ b;
- \\ return if (cond)
- \\ a
- \\ else if (cond)
- \\ b
- \\ else
- \\ c;
- \\}
- \\
- );
-}
-
-test "zig fmt: respect line breaks after infix operators" {
- try testCanonical(
- \\comptime {
- \\ self.crc =
- \\ lookup_tables[0][p[7]] ^
- \\ lookup_tables[1][p[6]] ^
- \\ lookup_tables[2][p[5]] ^
- \\ lookup_tables[3][p[4]] ^
- \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
- \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
- \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
- \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
- \\}
- \\
- );
-}
-
-test "zig fmt: fn decl with trailing comma" {
- try testTransform(
- \\fn foo(a: i32, b: i32,) void {}
- ,
- \\fn foo(
- \\ a: i32,
- \\ b: i32,
- \\) void {}
- \\
- );
-}
-
-test "zig fmt: enum decl with no trailing comma" {
- try testTransform(
- \\const StrLitKind = enum {Normal, C};
- ,
- \\const StrLitKind = enum { Normal, C };
- \\
- );
-}
-
-test "zig fmt: switch comment before prong" {
- try testCanonical(
- \\comptime {
- \\ switch (a) {
- \\ // hi
- \\ 0 => {},
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: struct literal no trailing comma" {
- try testTransform(
- \\const a = foo{ .x = 1, .y = 2 };
- \\const a = foo{ .x = 1,
- \\ .y = 2 };
- ,
- \\const a = foo{ .x = 1, .y = 2 };
- \\const a = foo{
- \\ .x = 1,
- \\ .y = 2,
- \\};
- \\
- );
-}
-
-test "zig fmt: struct literal containing a multiline expression" {
- try testTransform(
- \\const a = A{ .x = if (f1()) 10 else 20 };
- \\const a = A{ .x = if (f1()) 10 else 20, };
- \\const a = A{ .x = if (f1())
- \\ 10 else 20 };
- \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
- \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100, };
- \\const a = A{ .x = if (f1())
- \\ 10 else 20};
- \\const a = A{ .x = switch(g) {0 => "ok", else => "no"} };
- \\
- ,
- \\const a = A{ .x = if (f1()) 10 else 20 };
- \\const a = A{
- \\ .x = if (f1()) 10 else 20,
- \\};
- \\const a = A{
- \\ .x = if (f1())
- \\ 10
- \\ else
- \\ 20,
- \\};
- \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
- \\const a = A{
- \\ .x = if (f1()) 10 else 20,
- \\ .y = f2() + 100,
- \\};
- \\const a = A{
- \\ .x = if (f1())
- \\ 10
- \\ else
- \\ 20,
- \\};
- \\const a = A{
- \\ .x = switch (g) {
- \\ 0 => "ok",
- \\ else => "no",
- \\ },
- \\};
- \\
- );
-}
-
-test "zig fmt: array literal with hint" {
- try testTransform(
- \\const a = []u8{
- \\ 1, 2, //
- \\ 3,
- \\ 4,
- \\ 5,
- \\ 6,
- \\ 7 };
- \\const a = []u8{
- \\ 1, 2, //
- \\ 3,
- \\ 4,
- \\ 5,
- \\ 6,
- \\ 7, 8 };
- \\const a = []u8{
- \\ 1, 2, //
- \\ 3,
- \\ 4,
- \\ 5,
- \\ 6, // blah
- \\ 7, 8 };
- \\const a = []u8{
- \\ 1, 2, //
- \\ 3, //
- \\ 4,
- \\ 5,
- \\ 6,
- \\ 7 };
- \\const a = []u8{
- \\ 1,
- \\ 2,
- \\ 3, 4, //
- \\ 5, 6, //
- \\ 7, 8, //
- \\};
- ,
- \\const a = []u8{
- \\ 1, 2,
- \\ 3, 4,
- \\ 5, 6,
- \\ 7,
- \\};
- \\const a = []u8{
- \\ 1, 2,
- \\ 3, 4,
- \\ 5, 6,
- \\ 7, 8,
- \\};
- \\const a = []u8{
- \\ 1, 2,
- \\ 3, 4,
- \\ 5,
- \\ 6, // blah
- \\ 7,
- \\ 8,
- \\};
- \\const a = []u8{
- \\ 1, 2,
- \\ 3, //
- \\ 4,
- \\ 5, 6,
- \\ 7,
- \\};
- \\const a = []u8{
- \\ 1,
- \\ 2,
- \\ 3,
- \\ 4,
- \\ 5,
- \\ 6,
- \\ 7,
- \\ 8,
- \\};
- \\
- );
-}
-
-test "zig fmt: array literal veritical column alignment" {
- try testTransform(
- \\const a = []u8{
- \\ 1000, 200,
- \\ 30, 4,
- \\ 50000, 60
- \\};
- \\const a = []u8{0, 1, 2, 3, 40,
- \\ 4,5,600,7,
- \\ 80,
- \\ 9, 10, 11, 0, 13, 14, 15};
- \\
- ,
- \\const a = []u8{
- \\ 1000, 200,
- \\ 30, 4,
- \\ 50000, 60,
- \\};
- \\const a = []u8{
- \\ 0, 1, 2, 3, 40,
- \\ 4, 5, 600, 7, 80,
- \\ 9, 10, 11, 0, 13,
- \\ 14, 15,
- \\};
- \\
- );
-}
-
-test "zig fmt: multiline string with backslash at end of line" {
- try testCanonical(
- \\comptime {
- \\ err(
- \\ \\\
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: multiline string parameter in fn call with trailing comma" {
- try testCanonical(
- \\fn foo() void {
- \\ try stdout.print(
- \\ \\ZIG_CMAKE_BINARY_DIR {}
- \\ \\ZIG_C_HEADER_FILES {}
- \\ \\ZIG_DIA_GUIDS_LIB {}
- \\ \\
- \\ ,
- \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
- \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
- \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: trailing comma on fn call" {
- try testCanonical(
- \\comptime {
- \\ var module = try Module.create(
- \\ allocator,
- \\ zig_lib_dir,
- \\ full_cache_dir,
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: multi line arguments without last comma" {
- try testTransform(
- \\pub fn foo(
- \\ a: usize,
- \\ b: usize,
- \\ c: usize,
- \\ d: usize
- \\) usize {
- \\ return a + b + c + d;
- \\}
- \\
- ,
- \\pub fn foo(a: usize, b: usize, c: usize, d: usize) usize {
- \\ return a + b + c + d;
- \\}
- \\
- );
-}
-
-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 {
- \\ k: usize, s: u32, t: u32
- \\};
- \\
- );
-}
-
-test "zig fmt: extra newlines at the end" {
- try testTransform(
- \\const a = b;
- \\
- \\
- \\
- ,
- \\const a = b;
- \\
- );
-}
-
-test "zig fmt: simple asm" {
- try testTransform(
- \\comptime {
- \\ asm volatile (
- \\ \\.globl aoeu;
- \\ \\.type aoeu, @function;
- \\ \\.set aoeu, derp;
- \\ );
- \\
- \\ asm ("not real assembly"
- \\ :[a] "x" (x),);
- \\ asm ("not real assembly"
- \\ :[a] "x" (->i32),:[a] "x" (1),);
- \\ asm ("still not real assembly"
- \\ :::"a","b",);
- \\}
- ,
- \\comptime {
- \\ asm volatile (
- \\ \\.globl aoeu;
- \\ \\.type aoeu, @function;
- \\ \\.set aoeu, derp;
- \\ );
- \\
- \\ asm ("not real assembly"
- \\ : [a] "x" (x)
- \\ );
- \\ asm ("not real assembly"
- \\ : [a] "x" (-> i32)
- \\ : [a] "x" (1)
- \\ );
- \\ asm ("still not real assembly"
- \\ :
- \\ :
- \\ : "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(
- \\fn switch_cases(x: i32) void {
- \\ switch (x) {
- \\ 1,2,3 => {},
- \\ 4,5, => {},
- \\ 6... 8, => {},
- \\ else => {},
- \\ }
- \\}
- ,
- \\fn switch_cases(x: i32) void {
- \\ switch (x) {
- \\ 1, 2, 3 => {},
- \\ 4,
- \\ 5,
- \\ => {},
- \\ 6...8 => {},
- \\ else => {},
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: slice align" {
- try testCanonical(
- \\const A = struct {
- \\ items: []align(A) T,
- \\};
- \\
- );
-}
-
-test "zig fmt: add trailing comma to array literal" {
- try testTransform(
- \\comptime {
- \\ return []u16{'m', 's', 'y', 's', '-' // hi
- \\ };
- \\ return []u16{'m', 's', 'y', 's',
- \\ '-'};
- \\ return []u16{'m', 's', 'y', 's', '-'};
- \\}
- ,
- \\comptime {
- \\ return []u16{
- \\ 'm', 's', 'y', 's', '-', // hi
- \\ };
- \\ return []u16{
- \\ 'm', 's', 'y', 's',
- \\ '-',
- \\ };
- \\ return []u16{ 'm', 's', 'y', 's', '-' };
- \\}
- \\
- );
-}
-
-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: float literal with exponent" {
- try testCanonical(
- \\test "bit field alignment" {
- \\ assert(@TypeOf(&blah.b) == *align(1:3:6) const u3);
- \\}
- \\
- );
-}
-
-test "zig fmt: float literal with exponent" {
- try testCanonical(
- \\test "aoeu" {
- \\ switch (state) {
- \\ TermState.Start => switch (c) {
- \\ '\x1b' => state = TermState.Escape,
- \\ else => try out.writeByte(c),
- \\ },
- \\ }
- \\}
- \\
- );
-}
-test "zig fmt: float literal with exponent" {
- try testCanonical(
- \\pub const f64_true_min = 4.94065645841246544177e-324;
- \\const threshold = 0x1.a827999fcef32p+1022;
- \\
- );
-}
-
-test "zig fmt: if-else end of comptime" {
- try testCanonical(
- \\comptime {
- \\ if (a) {
- \\ b();
- \\ } else {
- \\ b();
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: nested blocks" {
- try testCanonical(
- \\comptime {
- \\ {
- \\ {
- \\ {
- \\ a();
- \\ }
- \\ }
- \\ }
- \\}
- \\
- );
-}
-
-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(
- \\comptime {
- \\ a = b;
- \\
- \\ a = b;
- \\}
- \\
- );
-}
-
-test "zig fmt: ptr deref operator and unwrap optional operator" {
- try testCanonical(
- \\const a = b.*;
- \\const a = b.?;
- \\
- );
-}
-
-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" {
- \\switch (self.init_arg_expr) {
- \\ InitArg.Type => |t| { },
- \\ InitArg.None,
- \\ InitArg.Enum => { }
- \\}
- \\ switch (self.init_arg_expr) {
- \\ InitArg.Type => |t| { },
- \\ InitArg.None,
- \\ InitArg.Enum => { }//line comment
- \\ }
- \\}
- ,
- \\test "aoeu" {
- \\ switch (self.init_arg_expr) {
- \\ InitArg.Type => |t| {},
- \\ InitArg.None, InitArg.Enum => {},
- \\ }
- \\ switch (self.init_arg_expr) {
- \\ InitArg.Type => |t| {},
- \\ InitArg.None, InitArg.Enum => {}, //line comment
- \\ }
- \\}
- \\
- );
-}
-
-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(
- \\test "" {
- \\ foo() catch |err| switch (err) {};
- \\}
- \\
- );
-}
-
-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: 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)) {
- \\ A = 20,
- \\ B = 40,
- \\ C = 60,
- \\ D = 1000,
- \\};
- \\
- );
-}
-
-test "zig fmt: resume from suspend block" {
- try testCanonical(
- \\fn foo() void {
- \\ suspend {
- \\ resume @frame();
- \\ }
- \\}
- \\
- );
-}
-
-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");
- \\
- \\pub fn main() !void {
- \\ var stdout_file = std.io.getStdOut;
- \\ var stdout_file = std.io.getStdOut;
- \\
- \\ var stdout_file = std.io.getStdOut;
- \\ var stdout_file = std.io.getStdOut;
- \\}
- \\
- );
-}
-
-test "zig fmt: return types" {
- try testCanonical(
- \\pub fn main() !void {}
- \\pub fn main() anytype {}
- \\pub fn main() i32 {}
- \\
- );
-}
-
-test "zig fmt: imports" {
- try testCanonical(
- \\const std = @import("std");
- \\const std = @import();
- \\
- );
-}
-
-test "zig fmt: global declarations" {
- try testCanonical(
- \\const a = b;
- \\pub const a = b;
- \\var a = b;
- \\pub var a = b;
- \\const a: i32 = b;
- \\pub const a: i32 = b;
- \\var a: i32 = b;
- \\pub var a: i32 = b;
- \\extern const a: i32 = b;
- \\pub extern const a: i32 = b;
- \\extern var a: i32 = b;
- \\pub extern var a: i32 = b;
- \\extern "a" const a: i32 = b;
- \\pub extern "a" const a: i32 = b;
- \\extern "a" var a: i32 = b;
- \\pub extern "a" var a: i32 = b;
- \\
- );
-}
-
-test "zig fmt: extern declaration" {
- try testCanonical(
- \\extern var foo: c_int;
- \\
- );
-}
-
-test "zig fmt: alignment" {
- try testCanonical(
- \\var foo: c_int align(1);
- \\
- );
-}
-
-test "zig fmt: C main" {
- try testCanonical(
- \\fn main(argc: c_int, argv: **u8) c_int {
- \\ const a = b;
- \\}
- \\
- );
-}
-
-test "zig fmt: return" {
- try testCanonical(
- \\fn foo(argc: c_int, argv: **u8) c_int {
- \\ return 0;
- \\}
- \\
- \\fn bar() void {
- \\ return;
- \\}
- \\
- );
-}
-
-test "zig fmt: pointer attributes" {
- try testCanonical(
- \\extern fn f1(s: *align(*u8) u8) c_int;
- \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
- \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
- \\extern fn f4(s: *align(1) const volatile u8) c_int;
- \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
- \\
- );
-}
-
-test "zig fmt: slice attributes" {
- try testCanonical(
- \\extern fn f1(s: *align(*u8) u8) c_int;
- \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
- \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
- \\extern fn f4(s: *align(1) const volatile u8) c_int;
- \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
- \\
- );
-}
-
-test "zig fmt: test declaration" {
- try testCanonical(
- \\test "test name" {
- \\ const a = 1;
- \\ var b = 1;
- \\}
- \\
- );
-}
-
-test "zig fmt: infix operators" {
- try testCanonical(
- \\test "infix operators" {
- \\ var i = undefined;
- \\ i = 2;
- \\ i *= 2;
- \\ i |= 2;
- \\ i ^= 2;
- \\ i <<= 2;
- \\ i >>= 2;
- \\ i &= 2;
- \\ i *= 2;
- \\ i *%= 2;
- \\ i -= 2;
- \\ i -%= 2;
- \\ i += 2;
- \\ i +%= 2;
- \\ i /= 2;
- \\ i %= 2;
- \\ _ = i == i;
- \\ _ = i != i;
- \\ _ = i != i;
- \\ _ = i.i;
- \\ _ = i || i;
- \\ _ = i!i;
- \\ _ = i ** i;
- \\ _ = i ++ i;
- \\ _ = i orelse i;
- \\ _ = i % i;
- \\ _ = i / i;
- \\ _ = i *% i;
- \\ _ = i * i;
- \\ _ = i -% i;
- \\ _ = i - i;
- \\ _ = i +% i;
- \\ _ = i + i;
- \\ _ = i << i;
- \\ _ = i >> i;
- \\ _ = i & i;
- \\ _ = i ^ i;
- \\ _ = i | i;
- \\ _ = i >= i;
- \\ _ = i <= i;
- \\ _ = i > i;
- \\ _ = i < i;
- \\ _ = i and i;
- \\ _ = i or i;
- \\}
- \\
- );
-}
-
-test "zig fmt: precedence" {
- try testCanonical(
- \\test "precedence" {
- \\ a!b();
- \\ (a!b)();
- \\ !a!b;
- \\ !(a!b);
- \\ !a{};
- \\ !(a{});
- \\ a + b{};
- \\ (a + b){};
- \\ a << b + c;
- \\ (a << b) + c;
- \\ a & b << c;
- \\ (a & b) << c;
- \\ a ^ b & c;
- \\ (a ^ b) & c;
- \\ a | b ^ c;
- \\ (a | b) ^ c;
- \\ a == b | c;
- \\ (a == b) | c;
- \\ a and b == c;
- \\ (a and b) == c;
- \\ a or b and c;
- \\ (a or b) and c;
- \\ (a or b) and c;
- \\}
- \\
- );
-}
-
-test "zig fmt: prefix operators" {
- try testCanonical(
- \\test "prefix operators" {
- \\ try return --%~!&0;
- \\}
- \\
- );
-}
-
-test "zig fmt: call expression" {
- try testCanonical(
- \\test "test calls" {
- \\ a();
- \\ a(1);
- \\ a(1, 2);
- \\ a(1, 2) + a(1, 2);
- \\}
- \\
- );
-}
-
-test "zig fmt: anytype type" {
- try testCanonical(
- \\fn print(args: anytype) anytype {}
- \\
- );
-}
-
-test "zig fmt: functions" {
- try testCanonical(
- \\extern fn puts(s: *const u8) c_int;
- \\extern "c" fn puts(s: *const u8) c_int;
- \\export fn puts(s: *const u8) c_int;
- \\inline fn puts(s: *const u8) c_int;
- \\noinline fn puts(s: *const u8) c_int;
- \\pub extern fn puts(s: *const u8) c_int;
- \\pub extern "c" fn puts(s: *const u8) c_int;
- \\pub export fn puts(s: *const u8) c_int;
- \\pub inline fn puts(s: *const u8) c_int;
- \\pub noinline fn puts(s: *const u8) c_int;
- \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
- \\
- );
-}
-
-test "zig fmt: multiline string" {
- try testCanonical(
- \\test "" {
- \\ const s1 =
- \\ \\one
- \\ \\two)
- \\ \\three
- \\ ;
- \\ const s3 = // hi
- \\ \\one
- \\ \\two)
- \\ \\three
- \\ ;
- \\}
- \\
- );
-}
-
-test "zig fmt: values" {
- try testCanonical(
- \\test "values" {
- \\ 1;
- \\ 1.0;
- \\ "string";
- \\ 'c';
- \\ true;
- \\ false;
- \\ null;
- \\ undefined;
- \\ anyerror;
- \\ this;
- \\ unreachable;
- \\}
- \\
- );
-}
-
-test "zig fmt: indexing" {
- try testCanonical(
- \\test "test index" {
- \\ a[0];
- \\ a[0 + 5];
- \\ a[0..];
- \\ a[0..5];
- \\ a[a[0]];
- \\ a[a[0..]];
- \\ a[a[0..5]];
- \\ a[a[0]..];
- \\ a[a[0..5]..];
- \\ a[a[0]..a[0]];
- \\ a[a[0..5]..a[0]];
- \\ a[a[0..5]..a[0..5]];
- \\}
- \\
- );
-}
-
-test "zig fmt: struct declaration" {
- try testCanonical(
- \\const S = struct {
- \\ const Self = @This();
- \\ f1: u8,
- \\ f3: u8,
- \\
- \\ f2: u8,
- \\
- \\ fn method(self: *Self) Self {
- \\ return self.*;
- \\ }
- \\};
- \\
- \\const Ps = packed struct {
- \\ a: u8,
- \\ b: u8,
- \\
- \\ c: u8,
- \\};
- \\
- \\const Es = extern struct {
- \\ a: u8,
- \\ b: u8,
- \\
- \\ c: u8,
- \\};
- \\
- );
-}
-
-test "zig fmt: enum declaration" {
- try testCanonical(
- \\const E = enum {
- \\ Ok,
- \\ SomethingElse = 0,
- \\};
- \\
- \\const E2 = enum(u8) {
- \\ Ok,
- \\ SomethingElse = 255,
- \\ SomethingThird,
- \\};
- \\
- \\const Ee = extern enum {
- \\ Ok,
- \\ SomethingElse,
- \\ SomethingThird,
- \\};
- \\
- \\const Ep = packed enum {
- \\ Ok,
- \\ SomethingElse,
- \\ SomethingThird,
- \\};
- \\
- );
-}
-
-test "zig fmt: union declaration" {
- try testCanonical(
- \\const U = union {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
- \\
- \\const Ue = union(enum) {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
- \\
- \\const E = enum {
- \\ Int,
- \\ Float,
- \\ None,
- \\ Bool,
- \\};
- \\
- \\const Ue2 = union(E) {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
- \\
- \\const Eu = extern union {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
- \\
- );
-}
-
-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: catch" {
- try testCanonical(
- \\test "catch" {
- \\ const a: anyerror!u8 = 0;
- \\ _ = a catch return;
- \\ _ = a catch |err| return;
- \\}
- \\
- );
-}
-
-test "zig fmt: blocks" {
- try testCanonical(
- \\test "blocks" {
- \\ {
- \\ const a = 0;
- \\ const b = 0;
- \\ }
- \\
- \\ blk: {
- \\ const a = 0;
- \\ const b = 0;
- \\ }
- \\
- \\ const r = blk: {
- \\ const a = 0;
- \\ const b = 0;
- \\ };
- \\}
- \\
- );
-}
-
-test "zig fmt: switch" {
- try testCanonical(
- \\test "switch" {
- \\ switch (0) {
- \\ 0 => {},
- \\ 1 => unreachable,
- \\ 2, 3 => {},
- \\ 4...7 => {},
- \\ 1 + 4 * 3 + 22 => {},
- \\ else => {
- \\ const a = 1;
- \\ const b = a;
- \\ },
- \\ }
- \\
- \\ const res = switch (0) {
- \\ 0 => 0,
- \\ 1 => 2,
- \\ 1 => a = 4,
- \\ else => 4,
- \\ };
- \\
- \\ const Union = union(enum) {
- \\ Int: i64,
- \\ Float: f64,
- \\ };
- \\
- \\ switch (u) {
- \\ Union.Int => |int| {},
- \\ Union.Float => |*float| unreachable,
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: while" {
- try testCanonical(
- \\test "while" {
- \\ while (10 < 1) unreachable;
- \\
- \\ while (10 < 1) unreachable else unreachable;
- \\
- \\ while (10 < 1) {
- \\ unreachable;
- \\ }
- \\
- \\ while (10 < 1)
- \\ unreachable;
- \\
- \\ var i: usize = 0;
- \\ while (i < 10) : (i += 1) {
- \\ continue;
- \\ }
- \\
- \\ i = 0;
- \\ while (i < 10) : (i += 1)
- \\ continue;
- \\
- \\ i = 0;
- \\ var j: usize = 0;
- \\ while (i < 10) : ({
- \\ i += 1;
- \\ j += 1;
- \\ }) {
- \\ continue;
- \\ }
- \\
- \\ var a: ?u8 = 2;
- \\ while (a) |v| : (a = null) {
- \\ continue;
- \\ }
- \\
- \\ while (a) |v| : (a = null)
- \\ unreachable;
- \\
- \\ label: while (10 < 0) {
- \\ unreachable;
- \\ }
- \\
- \\ const res = while (0 < 10) {
- \\ break 7;
- \\ } else {
- \\ unreachable;
- \\ };
- \\
- \\ const res = while (0 < 10)
- \\ break 7
- \\ else
- \\ unreachable;
- \\
- \\ var a: anyerror!u8 = 0;
- \\ while (a) |v| {
- \\ a = error.Err;
- \\ } else |err| {
- \\ i = 1;
- \\ }
- \\
- \\ comptime var k: usize = 0;
- \\ inline while (i < 10) : (i += 1)
- \\ j += 2;
- \\}
- \\
- );
-}
-
-test "zig fmt: for" {
- try testCanonical(
- \\test "for" {
- \\ for (a) |v| {
- \\ continue;
- \\ }
- \\
- \\ for (a) |v| continue;
- \\
- \\ for (a) |v| continue else return;
- \\
- \\ for (a) |v| {
- \\ continue;
- \\ } else return;
- \\
- \\ for (a) |v| continue else {
- \\ return;
- \\ }
- \\
- \\ for (a) |v|
- \\ continue
- \\ else
- \\ return;
- \\
- \\ for (a) |v|
- \\ continue;
- \\
- \\ for (a) |*v|
- \\ continue;
- \\
- \\ for (a) |v, i| {
- \\ continue;
- \\ }
- \\
- \\ for (a) |v, i|
- \\ continue;
- \\
- \\ for (a) |b| switch (b) {
- \\ c => {},
- \\ d => {},
- \\ };
- \\
- \\ for (a) |b|
- \\ switch (b) {
- \\ c => {},
- \\ d => {},
- \\ };
- \\
- \\ const res = for (a) |v, i| {
- \\ break v;
- \\ } else {
- \\ unreachable;
- \\ };
- \\
- \\ var num: usize = 0;
- \\ inline for (a) |v, i| {
- \\ num += v;
- \\ num += i;
- \\ }
- \\}
- \\
- );
-
- try testTransform(
- \\test "fix for" {
- \\ for (a) |x|
- \\ f(x) else continue;
- \\}
- \\
- ,
- \\test "fix for" {
- \\ for (a) |x|
- \\ f(x)
- \\ else continue;
- \\}
- \\
- );
-}
-
-test "zig fmt: if" {
- try testCanonical(
- \\test "if" {
- \\ if (10 < 0) {
- \\ unreachable;
- \\ }
- \\
- \\ if (10 < 0) unreachable;
- \\
- \\ if (10 < 0) {
- \\ unreachable;
- \\ } else {
- \\ const a = 20;
- \\ }
- \\
- \\ if (10 < 0) {
- \\ unreachable;
- \\ } else if (5 < 0) {
- \\ unreachable;
- \\ } else {
- \\ const a = 20;
- \\ }
- \\
- \\ const is_world_broken = if (10 < 0) true else false;
- \\ const some_number = 1 + if (10 < 0) 2 else 3;
- \\
- \\ const a: ?u8 = 10;
- \\ const b: ?u8 = null;
- \\ if (a) |v| {
- \\ const some = v;
- \\ } else if (b) |*v| {
- \\ unreachable;
- \\ } else {
- \\ const some = 10;
- \\ }
- \\
- \\ const non_null_a = if (a) |v| v else 0;
- \\
- \\ const a_err: anyerror!u8 = 0;
- \\ if (a_err) |v| {
- \\ const p = v;
- \\ } else |err| {
- \\ unreachable;
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: defer" {
- try testCanonical(
- \\test "defer" {
- \\ var i: usize = 0;
- \\ defer i = 1;
- \\ defer {
- \\ i += 2;
- \\ i *= i;
- \\ }
- \\
- \\ errdefer i += 3;
- \\ errdefer {
- \\ i += 2;
- \\ i /= i;
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: comptime" {
- try testCanonical(
- \\fn a() u8 {
- \\ return 5;
- \\}
- \\
- \\fn b(comptime i: u8) u8 {
- \\ return i;
- \\}
- \\
- \\const av = comptime a();
- \\const av2 = comptime blk: {
- \\ var res = a();
- \\ res *= b(2);
- \\ break :blk res;
- \\};
- \\
- \\comptime {
- \\ _ = a();
- \\}
- \\
- \\test "comptime" {
- \\ const av3 = comptime a();
- \\ const av4 = comptime blk: {
- \\ var res = a();
- \\ res *= a();
- \\ break :blk res;
- \\ };
- \\
- \\ comptime var i = 0;
- \\ comptime {
- \\ i = a();
- \\ i += b(i);
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: fn type" {
- try testCanonical(
- \\fn a(i: u8) u8 {
- \\ return i + 1;
- \\}
- \\
- \\const a: fn (u8) u8 = undefined;
- \\const b: fn (u8) callconv(.Naked) u8 = undefined;
- \\const ap: fn (u8) u8 = a;
- \\
- );
-}
-
-test "zig fmt: inline asm" {
- try testCanonical(
- \\pub fn syscall1(number: usize, arg1: usize) usize {
- \\ return asm volatile ("syscall"
- \\ : [ret] "={rax}" (-> usize)
- \\ : [number] "{rax}" (number),
- \\ [arg1] "{rdi}" (arg1)
- \\ : "rcx", "r11"
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: async functions" {
- try testCanonical(
- \\fn simpleAsyncFn() void {
- \\ const a = async a.b();
- \\ x += 1;
- \\ suspend;
- \\ x += 1;
- \\ suspend;
- \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
- \\ await p;
- \\}
- \\
- \\test "suspend, resume, await" {
- \\ const p: anyframe = async testAsyncSeq();
- \\ resume p;
- \\ await p;
- \\}
- \\
- );
-}
-
-test "zig fmt: nosuspend" {
- try testCanonical(
- \\const a = nosuspend foo();
- \\
- );
-}
-
-test "zig fmt: Block after if" {
- try testCanonical(
- \\test "Block after if" {
- \\ if (true) {
- \\ const a = 0;
- \\ }
- \\
- \\ {
- \\ const a = 0;
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: use" {
- try testCanonical(
- \\usingnamespace @import("std");
- \\pub usingnamespace @import("std");
- \\
- );
-}
-
-test "zig fmt: string identifier" {
- try testCanonical(
- \\const @"a b" = @"c d".@"e f";
- \\fn @"g h"() void {}
- \\
- );
-}
-
-test "zig fmt: error return" {
- try testCanonical(
- \\fn err() anyerror {
- \\ call();
- \\ return error.InvalidArgs;
- \\}
- \\
- );
-}
-
-test "zig fmt: comptime block in container" {
- try testCanonical(
- \\pub fn container() type {
- \\ return struct {
- \\ comptime {
- \\ if (false) {
- \\ unreachable;
- \\ }
- \\ }
- \\ };
- \\}
- \\
- );
-}
-
-test "zig fmt: inline asm parameter alignment" {
- try testCanonical(
- \\pub fn main() void {
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ );
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ : [_] "" (-> usize),
- \\ [_] "" (-> usize)
- \\ );
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ :
- \\ : [_] "" (0),
- \\ [_] "" (0)
- \\ );
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ :
- \\ :
- \\ : "", ""
- \\ );
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ : [_] "" (-> usize),
- \\ [_] "" (-> usize)
- \\ : [_] "" (0),
- \\ [_] "" (0)
- \\ : "", ""
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: multiline string in array" {
- try testCanonical(
- \\const Foo = [][]const u8{
- \\ \\aaa
- \\ ,
- \\ \\bbb
- \\};
- \\
- \\fn bar() void {
- \\ const Foo = [][]const u8{
- \\ \\aaa
- \\ ,
- \\ \\bbb
- \\ };
- \\ const Bar = [][]const u8{ // comment here
- \\ \\aaa
- \\ \\
- \\ , // and another comment can go here
- \\ \\bbb
- \\ };
- \\}
- \\
- );
-}
-
-test "zig fmt: if type expr" {
- try testCanonical(
- \\const mycond = true;
- \\pub fn foo() if (mycond) i32 else void {
- \\ if (mycond) {
- \\ return 42;
- \\ }
- \\}
- \\
- );
-}
-test "zig fmt: file ends with struct field" {
- try testCanonical(
- \\a: bool
- \\
- );
-}
-
-test "zig fmt: comment after empty comment" {
- try testTransform(
- \\const x = true; //
- \\//
- \\//
- \\//a
- \\
- ,
- \\const x = true;
- \\//a
- \\
- );
-}
-
-test "zig fmt: line comment in array" {
- try testTransform(
- \\test "a" {
- \\ var arr = [_]u32{
- \\ 0
- \\ // 1,
- \\ // 2,
- \\ };
- \\}
- \\
- ,
- \\test "a" {
- \\ var arr = [_]u32{
- \\ 0, // 1,
- \\ // 2,
- \\ };
- \\}
- \\
- );
- try testCanonical(
- \\test "a" {
- \\ var arr = [_]u32{
- \\ 0,
- \\ // 1,
- \\ // 2,
- \\ };
- \\}
- \\
- );
-}
-
-test "zig fmt: comment after params" {
- try testTransform(
- \\fn a(
- \\ b: u32
- \\ // c: u32,
- \\ // d: u32,
- \\) void {}
- \\
- ,
- \\fn a(
- \\ b: u32, // c: u32,
- \\ // d: u32,
- \\) void {}
- \\
- );
- try testCanonical(
- \\fn a(
- \\ b: u32,
- \\ // c: u32,
- \\ // d: u32,
- \\) void {}
- \\
- );
-}
-
-test "zig fmt: comment in array initializer/access" {
- try testCanonical(
- \\test "a" {
- \\ var a = x{ //aa
- \\ //bb
- \\ };
- \\ var a = []x{ //aa
- \\ //bb
- \\ };
- \\ var b = [ //aa
- \\ _
- \\ ]x{ //aa
- \\ //bb
- \\ 9,
- \\ };
- \\ var c = b[ //aa
- \\ 0
- \\ ];
- \\ var d = [_
- \\ //aa
- \\ ]x{ //aa
- \\ //bb
- \\ 9,
- \\ };
- \\ var e = d[0
- \\ //aa
- \\ ];
- \\}
- \\
- );
-}
-
-test "zig fmt: comments at several places in struct init" {
- try testTransform(
- \\var bar = Bar{
- \\ .x = 10, // test
- \\ .y = "test"
- \\ // test
- \\};
- \\
- ,
- \\var bar = Bar{
- \\ .x = 10, // test
- \\ .y = "test", // test
- \\};
- \\
- );
-
- try testCanonical(
- \\var bar = Bar{ // test
- \\ .x = 10, // test
- \\ .y = "test",
- \\ // test
- \\};
- \\
- );
-}
-
-test "zig fmt: top level doc comments" {
- try testCanonical(
- \\//! tld 1
- \\//! tld 2
- \\//! tld 3
- \\
- \\// comment
- \\
- \\/// A doc
- \\const A = struct {
- \\ //! A tld 1
- \\ //! A tld 2
- \\ //! A tld 3
- \\};
- \\
- \\/// B doc
- \\const B = struct {
- \\ //! B tld 1
- \\ //! B tld 2
- \\ //! B tld 3
- \\
- \\ /// b doc
- \\ b: u32,
- \\};
- \\
- \\/// C doc
- \\const C = struct {
- \\ //! C tld 1
- \\ //! C tld 2
- \\ //! C tld 3
- \\
- \\ /// c1 doc
- \\ c1: u32,
- \\
- \\ //! C tld 4
- \\ //! C tld 5
- \\ //! C tld 6
- \\
- \\ /// c2 doc
- \\ c2: u32,
- \\};
- \\
- );
- try testCanonical(
- \\//! Top-level documentation.
- \\
- \\/// This is A
- \\pub const A = usize;
- \\
- );
- try testCanonical(
- \\//! Nothing here
- \\
- );
-}
-
-test "zig fmt: extern without container keyword returns error" {
- try testError(
- \\const container = extern {};
- \\
- , &[_]Error{
- .ExpectedExpr,
- .ExpectedVarDeclOrFn,
- });
-}
-
-test "zig fmt: integer literals with underscore separators" {
- try testTransform(
- \\const
- \\ x =
- \\ 1_234_567
- \\ +(0b0_1-0o7_0+0xff_FF ) + 0_0;
- ,
- \\const x =
- \\ 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 0_0;
- \\
- );
-}
-
-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: 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: convert async fn into callconv(.Async)" {
- try testTransform(
- \\async fn foo() void {}
- ,
- \\fn foo() callconv(.Async) void {}
- \\
- );
-}
-
-test "zig fmt: convert extern fn proto into callconv(.C)" {
- try testTransform(
- \\extern fn foo0() void {}
- \\const foo1 = extern fn () void;
- ,
- \\extern fn foo0() void {}
- \\const foo1 = fn () callconv(.C) void;
- \\
- );
-}
-
-test "zig fmt: C var args" {
- try testCanonical(
- \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
- \\
- );
-}
-
-test "zig fmt: Only indent multiline string literals in function calls" {
- try testCanonical(
- \\test "zig fmt:" {
- \\ try testTransform(
- \\ \\const X = struct {
- \\ \\ foo: i32, bar: i8 };
- \\ ,
- \\ \\const X = struct {
- \\ \\ foo: i32, bar: i8
- \\ \\};
- \\ \\
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: Don't add extra newline after if" {
- try testCanonical(
- \\pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: []const u8) !void {
- \\ if (cwd().symLink(existing_path, new_path, .{})) {
- \\ return;
- \\ }
- \\}
- \\
- );
-}
-
-test "zig fmt: comments in ternary ifs" {
- try testCanonical(
- \\const x = if (true) {
- \\ 1;
- \\} else if (false)
- \\ // Comment
- \\ 0;
- \\const y = if (true)
- \\ // Comment
- \\ 1
- \\else
- \\ 0;
- \\
- \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
- \\
- );
-}
-
-test "zig fmt: test comments in field access chain" {
- try testCanonical(
- \\pub const str = struct {
- \\ pub const Thing = more.more //
- \\ .more() //
- \\ .more().more() //
- \\ .more() //
- \\ // .more() //
- \\ .more() //
- \\ .more();
- \\ data: Data,
- \\};
- \\
- \\pub const str = struct {
- \\ pub const Thing = more.more //
- \\ .more() //
- \\ // .more() //
- \\ // .more() //
- \\ // .more() //
- \\ .more() //
- \\ .more();
- \\ data: Data,
- \\};
- \\
- \\pub const str = struct {
- \\ pub const Thing = more //
- \\ .more //
- \\ .more() //
- \\ .more();
- \\ data: Data,
- \\};
- \\
- );
-}
-
-test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
- try testCanonical(
- \\fn foo() void {
- \\ z.display_message_dialog(
- \\ *const [323:0]u8,
- \\ \\Message Text
- \\ \\------------
- \\ \\xxxxxxxxxxxx
- \\ \\xxxxxxxxxxxx
- \\ ,
- \\ g.GtkMessageType.GTK_MESSAGE_WARNING,
- \\ null,
- \\ );
- \\
- \\ z.display_message_dialog(*const [323:0]u8,
- \\ \\Message Text
- \\ \\------------
- \\ \\xxxxxxxxxxxx
- \\ \\xxxxxxxxxxxx
- \\ , g.GtkMessageType.GTK_MESSAGE_WARNING, null);
- \\}
- \\
- );
-}
-
-test "zig fmt: Control flow statement as body of blockless if" {
- try testCanonical(
- \\pub fn main() void {
- \\ const zoom_node = if (focused_node == layout_first)
- \\ if (it.next()) {
- \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
- \\ } else null
- \\ else
- \\ focused_node;
- \\
- \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
- \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
- \\ } else null else
- \\ focused_node;
- \\
- \\ const zoom_node = if (focused_node == layout_first)
- \\ if (it.next()) {
- \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
- \\ } else null;
- \\
- \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
- \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
- \\ };
- \\
- \\ const zoom_node = if (focused_node == layout_first) for (nodes) |node| {
- \\ break node;
- \\ };
- \\
- \\ const zoom_node = if (focused_node == layout_first) switch (nodes) {
- \\ 0 => 0,
- \\ } else
- \\ focused_node;
- \\}
- \\
- );
-}
-
-test "zig fmt: " {
- try testCanonical(
- \\pub fn sendViewTags(self: Self) void {
- \\ var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));
- \\ while (it.next()) |node|
- \\ view_tags.append(node.view.current_tags) catch {
- \\ c.wl_resource_post_no_memory(self.wl_resource);
- \\ log.crit(.river_status, "out of memory", .{});
- \\ return;
- \\ };
- \\}
- \\
- );
-}
-
-test "zig fmt: allow trailing line comments to do manual array formatting" {
- try testCanonical(
- \\fn foo() void {
- \\ self.code.appendSliceAssumeCapacity(&[_]u8{
- \\ 0x55, // push rbp
- \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
- \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
- \\ });
- \\
- \\ di_buf.appendAssumeCapacity(&[_]u8{
- \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header
- \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs
- \\ DW.AT_low_pc, DW_FORM_addr,
- \\ DW.AT_high_pc, DW_FORM_addr,
- \\ DW.AT_name, DW_FORM_strp,
- \\ DW.AT_comp_dir, DW_FORM_strp,
- \\ DW.AT_producer, DW_FORM_strp,
- \\ DW.AT_language, DW_FORM_data2,
- \\ 0, 0, // sentinel
- \\ });
- \\
- \\ self.code.appendSliceAssumeCapacity(&[_]u8{
- \\ 0x55, // push rbp
- \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
- \\ // How do we handle this?
- \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
- \\ // Here's a blank line, should that be allowed?
- \\
- \\ 0x48, 0x89, 0xe5,
- \\ 0x33, 0x45,
- \\ // Now the comment breaks a single line -- how do we handle this?
- \\ 0x88,
- \\ });
- \\}
- \\
- );
-}
-
-test "zig fmt: multiline string literals should play nice with array initializers" {
- try testCanonical(
- \\fn main() void {
- \\ var a = .{.{.{.{.{.{.{.{
- \\ 0,
- \\ }}}}}}}};
- \\ myFunc(.{
- \\ "aaaaaaa", "bbbbbb", "ccccc",
- \\ "dddd", ("eee"), ("fff"),
- \\ ("gggg"),
- \\ // Line comment
- \\ \\Multiline String Literals can be quite long
- \\ ,
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ ,
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ ,
- \\ (
- \\ \\Multiline String Literals can be quite long
- \\ ),
- \\ .{
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ },
- \\ .{(
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ )},
- \\ .{
- \\ "xxxxxxx", "xxx",
- \\ (
- \\ \\ xxx
- \\ ),
- \\ "xxx", "xxx",
- \\ },
- \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" }, .{ "xxxxxxx", "xxx", "xxx", "xxx" },
- \\ "aaaaaaa", "bbbbbb", "ccccc", // -
- \\ "dddd", ("eee"), ("fff"),
- \\ .{
- \\ "xxx", "xxx",
- \\ (
- \\ \\ xxx
- \\ ),
- \\ "xxxxxxxxxxxxxx", "xxx",
- \\ },
- \\ .{
- \\ (
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ ),
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ },
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ });
- \\}
- \\
- );
-}
-
-test "zig fmt: use of comments and Multiline string literals may force the parameters over multiple lines" {
- try testCanonical(
- \\pub fn makeMemUndefined(qzz: []u8) i1 {
- \\ cases.add( // fixed bug #2032
- \\ "compile diagnostic string for top level decl type",
- \\ \\export fn entry() void {
- \\ \\ var foo: u32 = @This(){};
- \\ \\}
- \\ , &[_][]const u8{
- \\ "tmp.zig:2:27: error: type 'u32' does not support array initialization",
- \\ });
- \\ @compileError(
- \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
- \\ \\ Consider providing your own hash function.
- \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
- \\ \\ Consider providing your own hash function.
- \\ );
- \\ return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
- \\ .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
- \\}
- \\
- \\// This looks like garbage don't do this
- \\const rparen = tree.prevToken(
- \\// the first token for the annotation expressions is the left
- \\// parenthesis, hence the need for two prevToken
- \\ if (fn_proto.getAlignExpr()) |align_expr|
- \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))
- \\else if (fn_proto.getSectionExpr()) |section_expr|
- \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))
- \\else if (fn_proto.getCallconvExpr()) |callconv_expr|
- \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
- \\else switch (fn_proto.return_type) {
- \\ .Explicit => |node| node.firstToken(),
- \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),
- \\ .Invalid => unreachable,
- \\});
- \\
- );
-}
-
-test "zig fmt: single argument trailing commas in @builtins()" {
- try testCanonical(
- \\pub fn foo(qzz: []u8) i1 {
- \\ @panic(
- \\ foo,
- \\ );
- \\ panic(
- \\ foo,
- \\ );
- \\ @panic(
- \\ foo,
- \\ bar,
- \\ );
- \\}
- \\
- );
-}
-
-test "zig fmt: trailing comma should force multiline 1 column" {
- try testTransform(
- \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
- \\
- ,
- \\pub const UUID_NULL: uuid_t = [16]u8{
- \\ 0,
- \\ 0,
- \\ 0,
- \\ 0,
- \\};
- \\
- );
-}
-
-test "zig fmt: function params should align nicely" {
- try testCanonical(
- \\pub fn foo() void {
- \\ cases.addRuntimeSafety("slicing operator with sentinel",
- \\ \\const std = @import("std");
- \\ ++ check_panic_msg ++
- \\ \\pub fn main() void {
- \\ \\ var buf = [4]u8{'a','b','c',0};
- \\ \\ const slice = buf[0..:0];
- \\ \\}
- \\ );
- \\}
- \\
- );
-}
+test "zig fmt: simple top level comptime block" {
+ try testCanonical(
+ \\comptime {}
+ \\
+ );
+}
+
+//test "recovery: top level" {
+// try testError(
+// \\test "" {inline}
+// \\test "" {inline}
+// , &[_]Error{
+// .ExpectedInlinable,
+// .ExpectedInlinable,
+// });
+//}
+//
+//test "recovery: block statements" {
+// try testError(
+// \\test "" {
+// \\ foo + +;
+// \\ inline;
+// \\}
+// , &[_]Error{
+// .InvalidToken,
+// .ExpectedInlinable,
+// });
+//}
+//
+//test "recovery: missing comma" {
+// try testError(
+// \\test "" {
+// \\ switch (foo) {
+// \\ 2 => {}
+// \\ 3 => {}
+// \\ else => {
+// \\ foo && bar +;
+// \\ }
+// \\ }
+// \\}
+// , &[_]Error{
+// .ExpectedToken,
+// .ExpectedToken,
+// .InvalidAnd,
+// .InvalidToken,
+// });
+//}
+//
+//test "recovery: extra qualifier" {
+// try testError(
+// \\const a: *const const u8;
+// \\test ""
+// , &[_]Error{
+// .ExtraConstQualifier,
+// .ExpectedLBrace,
+// });
+//}
+//
+//test "recovery: missing return type" {
+// try testError(
+// \\fn foo() {
+// \\ a && b;
+// \\}
+// \\test ""
+// , &[_]Error{
+// .ExpectedReturnType,
+// .InvalidAnd,
+// .ExpectedLBrace,
+// });
+//}
+//
+//test "recovery: continue after invalid decl" {
+// try testError(
+// \\fn foo {
+// \\ inline;
+// \\}
+// \\pub test "" {
+// \\ async a && b;
+// \\}
+// , &[_]Error{
+// .ExpectedToken,
+// .ExpectedPubItem,
+// .ExpectedParamList,
+// .InvalidAnd,
+// });
+// try testError(
+// \\threadlocal test "" {
+// \\ @a && b;
+// \\}
+// , &[_]Error{
+// .ExpectedVarDecl,
+// .ExpectedParamList,
+// .InvalidAnd,
+// });
+//}
+//
+//test "recovery: invalid extern/inline" {
+// try testError(
+// \\inline test "" { a && b; }
+// , &[_]Error{
+// .ExpectedFn,
+// .InvalidAnd,
+// });
+// try testError(
+// \\extern "" test "" { a && b; }
+// , &[_]Error{
+// .ExpectedVarDeclOrFn,
+// .InvalidAnd,
+// });
+//}
+//
+//test "recovery: missing semicolon" {
+// try testError(
+// \\test "" {
+// \\ comptime a && b
+// \\ c && d
+// \\ @foo
+// \\}
+// , &[_]Error{
+// .InvalidAnd,
+// .ExpectedToken,
+// .InvalidAnd,
+// .ExpectedToken,
+// .ExpectedParamList,
+// .ExpectedToken,
+// });
+//}
+//
+//test "recovery: invalid container members" {
+// try testError(
+// \\usingnamespace;
+// \\foo+
+// \\bar@,
+// \\while (a == 2) { test "" {}}
+// \\test "" {
+// \\ a && b
+// \\}
+// , &[_]Error{
+// .ExpectedExpr,
+// .ExpectedToken,
+// .ExpectedToken,
+// .ExpectedContainerMembers,
+// .InvalidAnd,
+// .ExpectedToken,
+// });
+//}
+//
+//test "recovery: invalid parameter" {
+// try testError(
+// \\fn main() void {
+// \\ a(comptime T: type)
+// \\}
+// , &[_]Error{
+// .ExpectedToken,
+// });
+//}
+//
+//test "recovery: extra '}' at top level" {
+// try testError(
+// \\}}}
+// \\test "" {
+// \\ a && b;
+// \\}
+// , &[_]Error{
+// .ExpectedContainerMembers,
+// .ExpectedContainerMembers,
+// .ExpectedContainerMembers,
+// .InvalidAnd,
+// });
+//}
+//
+//test "recovery: mismatched bracket at top level" {
+// try testError(
+// \\const S = struct {
+// \\ arr: 128]?G
+// \\};
+// , &[_]Error{
+// .ExpectedToken,
+// });
+//}
+//
+//test "recovery: invalid global error set access" {
+// try testError(
+// \\test "" {
+// \\ error && foo;
+// \\}
+// , &[_]Error{
+// .ExpectedToken,
+// .ExpectedIdentifier,
+// .InvalidAnd,
+// });
+//}
+//
+//test "recovery: invalid asterisk after pointer dereference" {
+// try testError(
+// \\test "" {
+// \\ var sequence = "repeat".*** 10;
+// \\}
+// , &[_]Error{
+// .AsteriskAfterPointerDereference,
+// });
+// try testError(
+// \\test "" {
+// \\ var sequence = "repeat".** 10&&a;
+// \\}
+// , &[_]Error{
+// .AsteriskAfterPointerDereference,
+// .InvalidAnd,
+// });
+//}
+//
+//test "recovery: missing semicolon after if, for, while stmt" {
+// try testError(
+// \\test "" {
+// \\ if (foo) bar
+// \\ for (foo) |a| bar
+// \\ while (foo) bar
+// \\ a && b;
+// \\}
+// , &[_]Error{
+// .ExpectedSemiOrElse,
+// .ExpectedSemiOrElse,
+// .ExpectedSemiOrElse,
+// .InvalidAnd,
+// });
+//}
+//
+//test "recovery: invalid comptime" {
+// try testError(
+// \\comptime
+// , &[_]Error{
+// .ExpectedBlockOrField,
+// });
+//}
+//
+//test "recovery: missing block after for/while loops" {
+// try testError(
+// \\test "" { while (foo) }
+// , &[_]Error{
+// .ExpectedBlockOrAssignment,
+// });
+// try testError(
+// \\test "" { for (foo) |bar| }
+// , &[_]Error{
+// .ExpectedBlockOrAssignment,
+// });
+//}
+//
+//test "zig fmt: respect line breaks after var declarations" {
+// try testCanonical(
+// \\const crc =
+// \\ lookup_tables[0][p[7]] ^
+// \\ lookup_tables[1][p[6]] ^
+// \\ lookup_tables[2][p[5]] ^
+// \\ lookup_tables[3][p[4]] ^
+// \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
+// \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
+// \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
+// \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
+// \\
+// );
+//}
+//
+//test "zig fmt: multiline string mixed with comments" {
+// try testCanonical(
+// \\const s1 =
+// \\ //\\one
+// \\ \\two)
+// \\ \\three
+// \\;
+// \\const s2 =
+// \\ \\one
+// \\ \\two)
+// \\ //\\three
+// \\;
+// \\const s3 =
+// \\ \\one
+// \\ //\\two)
+// \\ \\three
+// \\;
+// \\const s4 =
+// \\ \\one
+// \\ //\\two
+// \\ \\three
+// \\ //\\four
+// \\ \\five
+// \\;
+// \\const a =
+// \\ 1;
+// \\
+// );
+//}
+//
+//test "zig fmt: empty file" {
+// try testCanonical(
+// \\
+// );
+//}
+//
+//test "zig fmt: if statment" {
+// try testCanonical(
+// \\test "" {
+// \\ if (optional()) |some|
+// \\ bar = some.foo();
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: top-level fields" {
+// try testCanonical(
+// \\a: did_you_know,
+// \\b: all_files_are,
+// \\structs: ?x,
+// \\
+// );
+//}
+//
+//test "zig fmt: decl between fields" {
+// try testError(
+// \\const S = struct {
+// \\ const foo = 2;
+// \\ const bar = 2;
+// \\ const baz = 2;
+// \\ a: usize,
+// \\ const foo1 = 2;
+// \\ const bar1 = 2;
+// \\ const baz1 = 2;
+// \\ b: usize,
+// \\};
+// , &[_]Error{
+// .DeclBetweenFields,
+// });
+//}
+//
+//test "zig fmt: eof after missing comma" {
+// try testError(
+// \\foo()
+// , &[_]Error{
+// .ExpectedToken,
+// });
+//}
+//
+//test "zig fmt: errdefer with payload" {
+// try testCanonical(
+// \\pub fn main() anyerror!void {
+// \\ errdefer |a| x += 1;
+// \\ errdefer |a| {}
+// \\ errdefer |a| {
+// \\ x += 1;
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: nosuspend block" {
+// try testCanonical(
+// \\pub fn main() anyerror!void {
+// \\ nosuspend {
+// \\ var foo: Foo = .{ .bar = 42 };
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: nosuspend await" {
+// try testCanonical(
+// \\fn foo() void {
+// \\ x = nosuspend await y;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: trailing comma in container declaration" {
+// try testCanonical(
+// \\const X = struct { foo: i32 };
+// \\const X = struct { foo: i32, bar: i32 };
+// \\const X = struct { foo: i32 = 1, bar: i32 = 2 };
+// \\const X = struct { foo: i32 align(4), bar: i32 align(4) };
+// \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };
+// \\
+// );
+// try testCanonical(
+// \\test "" {
+// \\ comptime {
+// \\ const X = struct {
+// \\ x: i32
+// \\ };
+// \\ }
+// \\}
+// \\
+// );
+// try testTransform(
+// \\const X = struct {
+// \\ foo: i32, bar: i8 };
+// ,
+// \\const X = struct {
+// \\ foo: i32, bar: i8
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: trailing comma in fn parameter list" {
+// try testCanonical(
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) i32 {}
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) align(8) i32 {}
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) linksection(".text") i32 {}
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) callconv(.C) i32 {}
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) align(8) linksection(".text") i32 {}
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) align(8) callconv(.C) i32 {}
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) align(8) linksection(".text") callconv(.C) i32 {}
+// \\pub fn f(
+// \\ a: i32,
+// \\ b: i32,
+// \\) linksection(".text") callconv(.C) i32 {}
+// \\
+// );
+//}
+//
+//test "zig fmt: comptime struct field" {
+// try testCanonical(
+// \\const Foo = struct {
+// \\ a: i32,
+// \\ comptime b: i32 = 1234,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: c pointer type" {
+// try testCanonical(
+// \\pub extern fn repro() [*c]const u8;
+// \\
+// );
+//}
+//
+//test "zig fmt: builtin call with trailing comma" {
+// try testCanonical(
+// \\pub fn main() void {
+// \\ @breakpoint();
+// \\ _ = @boolToInt(a);
+// \\ _ = @call(
+// \\ a,
+// \\ b,
+// \\ c,
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: asm expression with comptime content" {
+// try testCanonical(
+// \\comptime {
+// \\ asm ("foo" ++ "bar");
+// \\}
+// \\pub fn main() void {
+// \\ asm volatile ("foo" ++ "bar");
+// \\ asm volatile ("foo" ++ "bar"
+// \\ : [_] "" (x)
+// \\ );
+// \\ asm volatile ("foo" ++ "bar"
+// \\ : [_] "" (x)
+// \\ : [_] "" (y)
+// \\ );
+// \\ asm volatile ("foo" ++ "bar"
+// \\ : [_] "" (x)
+// \\ : [_] "" (y)
+// \\ : "h", "e", "l", "l", "o"
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: anytype struct field" {
+// try testCanonical(
+// \\pub const Pointer = struct {
+// \\ sentinel: anytype,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: sentinel-terminated array type" {
+// try testCanonical(
+// \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
+// \\ return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: sentinel-terminated slice type" {
+// try testCanonical(
+// \\pub fn toSlice(self: Buffer) [:0]u8 {
+// \\ return self.list.toSlice()[0..self.len()];
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: anon literal in array" {
+// try testCanonical(
+// \\var arr: [2]Foo = .{
+// \\ .{ .a = 2 },
+// \\ .{ .b = 3 },
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: alignment in anonymous literal" {
+// try testTransform(
+// \\const a = .{
+// \\ "U", "L", "F",
+// \\ "U'",
+// \\ "L'",
+// \\ "F'",
+// \\};
+// \\
+// ,
+// \\const a = .{
+// \\ "U", "L", "F",
+// \\ "U'", "L'", "F'",
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: anon struct literal syntax" {
+// try testCanonical(
+// \\const x = .{
+// \\ .a = b,
+// \\ .c = d,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: anon list literal syntax" {
+// try testCanonical(
+// \\const x = .{ a, b, c };
+// \\
+// );
+//}
+//
+//test "zig fmt: async function" {
+// try testCanonical(
+// \\pub const Server = struct {
+// \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void,
+// \\};
+// \\test "hi" {
+// \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: whitespace fixes" {
+// try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",
+// \\test "" {
+// \\ const hi = x;
+// \\}
+// \\// zig fmt: off
+// \\test ""{
+// \\ const a = b;}
+// \\
+// );
+//}
+//
+//test "zig fmt: while else err prong with no block" {
+// try testCanonical(
+// \\test "" {
+// \\ const result = while (returnError()) |value| {
+// \\ break value;
+// \\ } else |err| @as(i32, 2);
+// \\ expect(result == 2);
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: tagged union with enum values" {
+// try testCanonical(
+// \\const MultipleChoice2 = union(enum(u32)) {
+// \\ Unspecified1: i32,
+// \\ A: f32 = 20,
+// \\ Unspecified2: void,
+// \\ B: bool = 40,
+// \\ Unspecified3: i32,
+// \\ C: i8 = 60,
+// \\ Unspecified4: void,
+// \\ D: void = 1000,
+// \\ Unspecified5: i32,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: allowzero pointer" {
+// try testCanonical(
+// \\const T = [*]allowzero const u8;
+// \\
+// );
+//}
+//
+//test "zig fmt: enum literal" {
+// try testCanonical(
+// \\const x = .hi;
+// \\
+// );
+//}
+//
+//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(
+// \\const x = '\u{01f4a9}';
+// \\
+// );
+//}
+//
+//test "zig fmt: infix operator and then multiline string literal" {
+// try testCanonical(
+// \\const x = "" ++
+// \\ \\ hi
+// \\;
+// \\
+// );
+//}
+//
+//test "zig fmt: infix operator and then multiline string literal" {
+// try testCanonical(
+// \\const x = "" ++
+// \\ \\ hi0
+// \\ \\ hi1
+// \\ \\ hi2
+// \\;
+// \\
+// );
+//}
+//
+//test "zig fmt: C pointers" {
+// try testCanonical(
+// \\const Ptr = [*c]i32;
+// \\
+// );
+//}
+//
+//test "zig fmt: threadlocal" {
+// try testCanonical(
+// \\threadlocal var x: i32 = 1234;
+// \\
+// );
+//}
+//
+//test "zig fmt: linksection" {
+// try testCanonical(
+// \\export var aoeu: u64 linksection(".text.derp") = 1234;
+// \\export fn _start() linksection(".text.boot") callconv(.Naked) noreturn {}
+// \\
+// );
+//}
+//
+//test "zig fmt: correctly move doc comments on struct fields" {
+// try testTransform(
+// \\pub const section_64 = extern struct {
+// \\ sectname: [16]u8, /// name of this section
+// \\ segname: [16]u8, /// segment this section goes in
+// \\};
+// ,
+// \\pub const section_64 = extern struct {
+// \\ /// name of this section
+// \\ sectname: [16]u8,
+// \\ /// segment this section goes in
+// \\ segname: [16]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(
+// \\pub const S = struct {
+// \\ f: i32 align(32),
+// \\};
+// \\
+// );
+// try testCanonical(
+// \\pub const S = struct {
+// \\ f: i32 align(32) = 1,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: comment to disable/enable zig fmt first" {
+// try testCanonical(
+// \\// Test trailing comma syntax
+// \\// zig fmt: off
+// \\
+// \\const struct_trailing_comma = struct { x: i32, y: i32, };
+// );
+//}
+//
+//test "zig fmt: comment to disable/enable zig fmt" {
+// try testTransform(
+// \\const a = b;
+// \\// zig fmt: off
+// \\const c = d;
+// \\// zig fmt: on
+// \\const e = f;
+// ,
+// \\const a = b;
+// \\// zig fmt: off
+// \\const c = d;
+// \\// zig fmt: on
+// \\const e = f;
+// \\
+// );
+//}
+//
+//test "zig fmt: line comment following 'zig fmt: off'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\// Test
+// \\const e = f;
+// );
+//}
+//
+//test "zig fmt: doc comment following 'zig fmt: off'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\/// test
+// \\const e = f;
+// );
+//}
+//
+//test "zig fmt: line and doc comment following 'zig fmt: off'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\// test 1
+// \\/// test 2
+// \\const e = f;
+// );
+//}
+//
+//test "zig fmt: doc and line comment following 'zig fmt: off'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\/// test 1
+// \\// test 2
+// \\const e = f;
+// );
+//}
+//
+//test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\// zig fmt: on
+// \\// zig fmt: off
+// \\const e = f;
+// \\// zig fmt: off
+// \\// zig fmt: on
+// \\// zig fmt: off
+// \\const a = b;
+// \\// zig fmt: on
+// \\const c = d;
+// \\// zig fmt: on
+// \\
+// );
+//}
+//
+//test "zig fmt: line comment following 'zig fmt: on'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\const e = f;
+// \\// zig fmt: on
+// \\// test
+// \\const e = f;
+// \\
+// );
+//}
+//
+//test "zig fmt: doc comment following 'zig fmt: on'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\const e = f;
+// \\// zig fmt: on
+// \\/// test
+// \\const e = f;
+// \\
+// );
+//}
+//
+//test "zig fmt: line and doc comment following 'zig fmt: on'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\const e = f;
+// \\// zig fmt: on
+// \\// test1
+// \\/// test2
+// \\const e = f;
+// \\
+// );
+//}
+//
+//test "zig fmt: doc and line comment following 'zig fmt: on'" {
+// try testCanonical(
+// \\// zig fmt: off
+// \\const e = f;
+// \\// zig fmt: on
+// \\/// test1
+// \\// test2
+// \\const e = f;
+// \\
+// );
+//}
+//
+//test "zig fmt: pointer of unknown length" {
+// try testCanonical(
+// \\fn foo(ptr: [*]u8) void {}
+// \\
+// );
+//}
+//
+//test "zig fmt: spaces around slice operator" {
+// try testCanonical(
+// \\var a = b[c..d];
+// \\var a = b[c..d :0];
+// \\var a = b[c + 1 .. d];
+// \\var a = b[c + 1 ..];
+// \\var a = b[c .. d + 1];
+// \\var a = b[c .. d + 1 :0];
+// \\var a = b[c.a..d.e];
+// \\var a = b[c.a..d.e :0];
+// \\
+// );
+//}
+//
+//test "zig fmt: async call in if condition" {
+// try testCanonical(
+// \\comptime {
+// \\ if (async b()) {
+// \\ a();
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: 2nd arg multiline string" {
+// try testCanonical(
+// \\comptime {
+// \\ cases.addAsm("hello world linux x86_64",
+// \\ \\.text
+// \\ , "Hello, world!\n");
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: 2nd arg multiline string many args" {
+// try testCanonical(
+// \\comptime {
+// \\ cases.addAsm("hello world linux x86_64",
+// \\ \\.text
+// \\ , "Hello, world!\n", "Hello, world!\n");
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: final arg multiline string" {
+// try testCanonical(
+// \\comptime {
+// \\ cases.addAsm("hello world linux x86_64", "Hello, world!\n",
+// \\ \\.text
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: if condition wraps" {
+// try testTransform(
+// \\comptime {
+// \\ if (cond and
+// \\ cond) {
+// \\ return x;
+// \\ }
+// \\ while (cond and
+// \\ cond) {
+// \\ return x;
+// \\ }
+// \\ if (a == b and
+// \\ c) {
+// \\ a = b;
+// \\ }
+// \\ while (a == b and
+// \\ c) {
+// \\ a = b;
+// \\ }
+// \\ if ((cond and
+// \\ cond)) {
+// \\ return x;
+// \\ }
+// \\ while ((cond and
+// \\ cond)) {
+// \\ return x;
+// \\ }
+// \\ var a = if (a) |*f| x: {
+// \\ break :x &a.b;
+// \\ } else |err| err;
+// \\ var a = if (cond and
+// \\ cond) |*f|
+// \\ x: {
+// \\ break :x &a.b;
+// \\ } else |err| err;
+// \\}
+// ,
+// \\comptime {
+// \\ if (cond and
+// \\ cond)
+// \\ {
+// \\ return x;
+// \\ }
+// \\ while (cond and
+// \\ cond)
+// \\ {
+// \\ return x;
+// \\ }
+// \\ if (a == b and
+// \\ c)
+// \\ {
+// \\ a = b;
+// \\ }
+// \\ while (a == b and
+// \\ c)
+// \\ {
+// \\ a = b;
+// \\ }
+// \\ if ((cond and
+// \\ cond))
+// \\ {
+// \\ return x;
+// \\ }
+// \\ while ((cond and
+// \\ cond))
+// \\ {
+// \\ return x;
+// \\ }
+// \\ var a = if (a) |*f| x: {
+// \\ break :x &a.b;
+// \\ } else |err| err;
+// \\ var a = if (cond and
+// \\ cond) |*f|
+// \\ x: {
+// \\ break :x &a.b;
+// \\ } else |err| err;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: if condition has line break but must not wrap" {
+// try testCanonical(
+// \\comptime {
+// \\ if (self.user_input_options.put(
+// \\ name,
+// \\ UserInputOption{
+// \\ .name = name,
+// \\ .used = false,
+// \\ },
+// \\ ) catch unreachable) |*prev_value| {
+// \\ foo();
+// \\ bar();
+// \\ }
+// \\ if (put(
+// \\ a,
+// \\ b,
+// \\ )) {
+// \\ foo();
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: if condition has line break but must not wrap" {
+// try testCanonical(
+// \\comptime {
+// \\ if (self.user_input_options.put(name, UserInputOption{
+// \\ .name = name,
+// \\ .used = false,
+// \\ }) catch unreachable) |*prev_value| {
+// \\ foo();
+// \\ bar();
+// \\ }
+// \\ if (put(
+// \\ a,
+// \\ b,
+// \\ )) {
+// \\ foo();
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: function call with multiline argument" {
+// try testCanonical(
+// \\comptime {
+// \\ self.user_input_options.put(name, UserInputOption{
+// \\ .name = name,
+// \\ .used = false,
+// \\ });
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: same-line doc comment on variable declaration" {
+// try testTransform(
+// \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
+// \\pub const MAP_FILE = 0x0000; /// map from file (default)
+// \\
+// \\pub const EMEDIUMTYPE = 124; /// Wrong medium type
+// \\
+// \\// nameserver query return codes
+// \\pub const ENSROK = 0; /// DNS server returned answer with no data
+// ,
+// \\/// allocated from memory, swap space
+// \\pub const MAP_ANONYMOUS = 0x1000;
+// \\/// map from file (default)
+// \\pub const MAP_FILE = 0x0000;
+// \\
+// \\/// Wrong medium type
+// \\pub const EMEDIUMTYPE = 124;
+// \\
+// \\// nameserver query return codes
+// \\/// DNS server returned answer with no data
+// \\pub const ENSROK = 0;
+// \\
+// );
+//}
+//
+//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 {
+// \\ return if ((aInt & bInt) >= 0)
+// \\ if (aInt < bInt)
+// \\ GE_LESS
+// \\ else if (aInt == bInt)
+// \\ GE_EQUAL
+// \\ else
+// \\ GE_GREATER
+// \\ else if (aInt > bInt)
+// \\ GE_LESS
+// \\ else if (aInt == bInt)
+// \\ GE_EQUAL
+// \\ else
+// \\ GE_GREATER;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: respect line breaks in if-else" {
+// try testCanonical(
+// \\comptime {
+// \\ return if (cond) a else b;
+// \\ return if (cond)
+// \\ a
+// \\ else
+// \\ b;
+// \\ return if (cond)
+// \\ a
+// \\ else if (cond)
+// \\ b
+// \\ else
+// \\ c;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: respect line breaks after infix operators" {
+// try testCanonical(
+// \\comptime {
+// \\ self.crc =
+// \\ lookup_tables[0][p[7]] ^
+// \\ lookup_tables[1][p[6]] ^
+// \\ lookup_tables[2][p[5]] ^
+// \\ lookup_tables[3][p[4]] ^
+// \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
+// \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
+// \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
+// \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: fn decl with trailing comma" {
+// try testTransform(
+// \\fn foo(a: i32, b: i32,) void {}
+// ,
+// \\fn foo(
+// \\ a: i32,
+// \\ b: i32,
+// \\) void {}
+// \\
+// );
+//}
+//
+//test "zig fmt: enum decl with no trailing comma" {
+// try testTransform(
+// \\const StrLitKind = enum {Normal, C};
+// ,
+// \\const StrLitKind = enum { Normal, C };
+// \\
+// );
+//}
+//
+//test "zig fmt: switch comment before prong" {
+// try testCanonical(
+// \\comptime {
+// \\ switch (a) {
+// \\ // hi
+// \\ 0 => {},
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: struct literal no trailing comma" {
+// try testTransform(
+// \\const a = foo{ .x = 1, .y = 2 };
+// \\const a = foo{ .x = 1,
+// \\ .y = 2 };
+// ,
+// \\const a = foo{ .x = 1, .y = 2 };
+// \\const a = foo{
+// \\ .x = 1,
+// \\ .y = 2,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: struct literal containing a multiline expression" {
+// try testTransform(
+// \\const a = A{ .x = if (f1()) 10 else 20 };
+// \\const a = A{ .x = if (f1()) 10 else 20, };
+// \\const a = A{ .x = if (f1())
+// \\ 10 else 20 };
+// \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
+// \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100, };
+// \\const a = A{ .x = if (f1())
+// \\ 10 else 20};
+// \\const a = A{ .x = switch(g) {0 => "ok", else => "no"} };
+// \\
+// ,
+// \\const a = A{ .x = if (f1()) 10 else 20 };
+// \\const a = A{
+// \\ .x = if (f1()) 10 else 20,
+// \\};
+// \\const a = A{
+// \\ .x = if (f1())
+// \\ 10
+// \\ else
+// \\ 20,
+// \\};
+// \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
+// \\const a = A{
+// \\ .x = if (f1()) 10 else 20,
+// \\ .y = f2() + 100,
+// \\};
+// \\const a = A{
+// \\ .x = if (f1())
+// \\ 10
+// \\ else
+// \\ 20,
+// \\};
+// \\const a = A{
+// \\ .x = switch (g) {
+// \\ 0 => "ok",
+// \\ else => "no",
+// \\ },
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: array literal with hint" {
+// try testTransform(
+// \\const a = []u8{
+// \\ 1, 2, //
+// \\ 3,
+// \\ 4,
+// \\ 5,
+// \\ 6,
+// \\ 7 };
+// \\const a = []u8{
+// \\ 1, 2, //
+// \\ 3,
+// \\ 4,
+// \\ 5,
+// \\ 6,
+// \\ 7, 8 };
+// \\const a = []u8{
+// \\ 1, 2, //
+// \\ 3,
+// \\ 4,
+// \\ 5,
+// \\ 6, // blah
+// \\ 7, 8 };
+// \\const a = []u8{
+// \\ 1, 2, //
+// \\ 3, //
+// \\ 4,
+// \\ 5,
+// \\ 6,
+// \\ 7 };
+// \\const a = []u8{
+// \\ 1,
+// \\ 2,
+// \\ 3, 4, //
+// \\ 5, 6, //
+// \\ 7, 8, //
+// \\};
+// ,
+// \\const a = []u8{
+// \\ 1, 2,
+// \\ 3, 4,
+// \\ 5, 6,
+// \\ 7,
+// \\};
+// \\const a = []u8{
+// \\ 1, 2,
+// \\ 3, 4,
+// \\ 5, 6,
+// \\ 7, 8,
+// \\};
+// \\const a = []u8{
+// \\ 1, 2,
+// \\ 3, 4,
+// \\ 5,
+// \\ 6, // blah
+// \\ 7,
+// \\ 8,
+// \\};
+// \\const a = []u8{
+// \\ 1, 2,
+// \\ 3, //
+// \\ 4,
+// \\ 5, 6,
+// \\ 7,
+// \\};
+// \\const a = []u8{
+// \\ 1,
+// \\ 2,
+// \\ 3,
+// \\ 4,
+// \\ 5,
+// \\ 6,
+// \\ 7,
+// \\ 8,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: array literal veritical column alignment" {
+// try testTransform(
+// \\const a = []u8{
+// \\ 1000, 200,
+// \\ 30, 4,
+// \\ 50000, 60
+// \\};
+// \\const a = []u8{0, 1, 2, 3, 40,
+// \\ 4,5,600,7,
+// \\ 80,
+// \\ 9, 10, 11, 0, 13, 14, 15};
+// \\
+// ,
+// \\const a = []u8{
+// \\ 1000, 200,
+// \\ 30, 4,
+// \\ 50000, 60,
+// \\};
+// \\const a = []u8{
+// \\ 0, 1, 2, 3, 40,
+// \\ 4, 5, 600, 7, 80,
+// \\ 9, 10, 11, 0, 13,
+// \\ 14, 15,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: multiline string with backslash at end of line" {
+// try testCanonical(
+// \\comptime {
+// \\ err(
+// \\ \\\
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: multiline string parameter in fn call with trailing comma" {
+// try testCanonical(
+// \\fn foo() void {
+// \\ try stdout.print(
+// \\ \\ZIG_CMAKE_BINARY_DIR {}
+// \\ \\ZIG_C_HEADER_FILES {}
+// \\ \\ZIG_DIA_GUIDS_LIB {}
+// \\ \\
+// \\ ,
+// \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
+// \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
+// \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: trailing comma on fn call" {
+// try testCanonical(
+// \\comptime {
+// \\ var module = try Module.create(
+// \\ allocator,
+// \\ zig_lib_dir,
+// \\ full_cache_dir,
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: multi line arguments without last comma" {
+// try testTransform(
+// \\pub fn foo(
+// \\ a: usize,
+// \\ b: usize,
+// \\ c: usize,
+// \\ d: usize
+// \\) usize {
+// \\ return a + b + c + d;
+// \\}
+// \\
+// ,
+// \\pub fn foo(a: usize, b: usize, c: usize, d: usize) usize {
+// \\ return a + b + c + d;
+// \\}
+// \\
+// );
+//}
+//
+//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 {
+// \\ k: usize, s: u32, t: u32
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: extra newlines at the end" {
+// try testTransform(
+// \\const a = b;
+// \\
+// \\
+// \\
+// ,
+// \\const a = b;
+// \\
+// );
+//}
+//
+//test "zig fmt: simple asm" {
+// try testTransform(
+// \\comptime {
+// \\ asm volatile (
+// \\ \\.globl aoeu;
+// \\ \\.type aoeu, @function;
+// \\ \\.set aoeu, derp;
+// \\ );
+// \\
+// \\ asm ("not real assembly"
+// \\ :[a] "x" (x),);
+// \\ asm ("not real assembly"
+// \\ :[a] "x" (->i32),:[a] "x" (1),);
+// \\ asm ("still not real assembly"
+// \\ :::"a","b",);
+// \\}
+// ,
+// \\comptime {
+// \\ asm volatile (
+// \\ \\.globl aoeu;
+// \\ \\.type aoeu, @function;
+// \\ \\.set aoeu, derp;
+// \\ );
+// \\
+// \\ asm ("not real assembly"
+// \\ : [a] "x" (x)
+// \\ );
+// \\ asm ("not real assembly"
+// \\ : [a] "x" (-> i32)
+// \\ : [a] "x" (1)
+// \\ );
+// \\ asm ("still not real assembly"
+// \\ :
+// \\ :
+// \\ : "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(
+// \\fn switch_cases(x: i32) void {
+// \\ switch (x) {
+// \\ 1,2,3 => {},
+// \\ 4,5, => {},
+// \\ 6... 8, => {},
+// \\ else => {},
+// \\ }
+// \\}
+// ,
+// \\fn switch_cases(x: i32) void {
+// \\ switch (x) {
+// \\ 1, 2, 3 => {},
+// \\ 4,
+// \\ 5,
+// \\ => {},
+// \\ 6...8 => {},
+// \\ else => {},
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: slice align" {
+// try testCanonical(
+// \\const A = struct {
+// \\ items: []align(A) T,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: add trailing comma to array literal" {
+// try testTransform(
+// \\comptime {
+// \\ return []u16{'m', 's', 'y', 's', '-' // hi
+// \\ };
+// \\ return []u16{'m', 's', 'y', 's',
+// \\ '-'};
+// \\ return []u16{'m', 's', 'y', 's', '-'};
+// \\}
+// ,
+// \\comptime {
+// \\ return []u16{
+// \\ 'm', 's', 'y', 's', '-', // hi
+// \\ };
+// \\ return []u16{
+// \\ 'm', 's', 'y', 's',
+// \\ '-',
+// \\ };
+// \\ return []u16{ 'm', 's', 'y', 's', '-' };
+// \\}
+// \\
+// );
+//}
+//
+//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: float literal with exponent" {
+// try testCanonical(
+// \\test "bit field alignment" {
+// \\ assert(@TypeOf(&blah.b) == *align(1:3:6) const u3);
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: float literal with exponent" {
+// try testCanonical(
+// \\test "aoeu" {
+// \\ switch (state) {
+// \\ TermState.Start => switch (c) {
+// \\ '\x1b' => state = TermState.Escape,
+// \\ else => try out.writeByte(c),
+// \\ },
+// \\ }
+// \\}
+// \\
+// );
+//}
+//test "zig fmt: float literal with exponent" {
+// try testCanonical(
+// \\pub const f64_true_min = 4.94065645841246544177e-324;
+// \\const threshold = 0x1.a827999fcef32p+1022;
+// \\
+// );
+//}
+//
+//test "zig fmt: if-else end of comptime" {
+// try testCanonical(
+// \\comptime {
+// \\ if (a) {
+// \\ b();
+// \\ } else {
+// \\ b();
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: nested blocks" {
+// try testCanonical(
+// \\comptime {
+// \\ {
+// \\ {
+// \\ {
+// \\ a();
+// \\ }
+// \\ }
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//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(
+// \\comptime {
+// \\ a = b;
+// \\
+// \\ a = b;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: ptr deref operator and unwrap optional operator" {
+// try testCanonical(
+// \\const a = b.*;
+// \\const a = b.?;
+// \\
+// );
+//}
+//
+//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" {
+// \\switch (self.init_arg_expr) {
+// \\ InitArg.Type => |t| { },
+// \\ InitArg.None,
+// \\ InitArg.Enum => { }
+// \\}
+// \\ switch (self.init_arg_expr) {
+// \\ InitArg.Type => |t| { },
+// \\ InitArg.None,
+// \\ InitArg.Enum => { }//line comment
+// \\ }
+// \\}
+// ,
+// \\test "aoeu" {
+// \\ switch (self.init_arg_expr) {
+// \\ InitArg.Type => |t| {},
+// \\ InitArg.None, InitArg.Enum => {},
+// \\ }
+// \\ switch (self.init_arg_expr) {
+// \\ InitArg.Type => |t| {},
+// \\ InitArg.None, InitArg.Enum => {}, //line comment
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//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(
+// \\test "" {
+// \\ foo() catch |err| switch (err) {};
+// \\}
+// \\
+// );
+//}
+//
+//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: 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)) {
+// \\ A = 20,
+// \\ B = 40,
+// \\ C = 60,
+// \\ D = 1000,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: resume from suspend block" {
+// try testCanonical(
+// \\fn foo() void {
+// \\ suspend {
+// \\ resume @frame();
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//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");
+// \\
+// \\pub fn main() !void {
+// \\ var stdout_file = std.io.getStdOut;
+// \\ var stdout_file = std.io.getStdOut;
+// \\
+// \\ var stdout_file = std.io.getStdOut;
+// \\ var stdout_file = std.io.getStdOut;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: return types" {
+// try testCanonical(
+// \\pub fn main() !void {}
+// \\pub fn main() anytype {}
+// \\pub fn main() i32 {}
+// \\
+// );
+//}
+//
+//test "zig fmt: imports" {
+// try testCanonical(
+// \\const std = @import("std");
+// \\const std = @import();
+// \\
+// );
+//}
+//
+//test "zig fmt: global declarations" {
+// try testCanonical(
+// \\const a = b;
+// \\pub const a = b;
+// \\var a = b;
+// \\pub var a = b;
+// \\const a: i32 = b;
+// \\pub const a: i32 = b;
+// \\var a: i32 = b;
+// \\pub var a: i32 = b;
+// \\extern const a: i32 = b;
+// \\pub extern const a: i32 = b;
+// \\extern var a: i32 = b;
+// \\pub extern var a: i32 = b;
+// \\extern "a" const a: i32 = b;
+// \\pub extern "a" const a: i32 = b;
+// \\extern "a" var a: i32 = b;
+// \\pub extern "a" var a: i32 = b;
+// \\
+// );
+//}
+//
+//test "zig fmt: extern declaration" {
+// try testCanonical(
+// \\extern var foo: c_int;
+// \\
+// );
+//}
+//
+//test "zig fmt: alignment" {
+// try testCanonical(
+// \\var foo: c_int align(1);
+// \\
+// );
+//}
+//
+//test "zig fmt: C main" {
+// try testCanonical(
+// \\fn main(argc: c_int, argv: **u8) c_int {
+// \\ const a = b;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: return" {
+// try testCanonical(
+// \\fn foo(argc: c_int, argv: **u8) c_int {
+// \\ return 0;
+// \\}
+// \\
+// \\fn bar() void {
+// \\ return;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: pointer attributes" {
+// try testCanonical(
+// \\extern fn f1(s: *align(*u8) u8) c_int;
+// \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
+// \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
+// \\extern fn f4(s: *align(1) const volatile u8) c_int;
+// \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
+// \\
+// );
+//}
+//
+//test "zig fmt: slice attributes" {
+// try testCanonical(
+// \\extern fn f1(s: *align(*u8) u8) c_int;
+// \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
+// \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
+// \\extern fn f4(s: *align(1) const volatile u8) c_int;
+// \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
+// \\
+// );
+//}
+//
+//test "zig fmt: test declaration" {
+// try testCanonical(
+// \\test "test name" {
+// \\ const a = 1;
+// \\ var b = 1;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: infix operators" {
+// try testCanonical(
+// \\test "infix operators" {
+// \\ var i = undefined;
+// \\ i = 2;
+// \\ i *= 2;
+// \\ i |= 2;
+// \\ i ^= 2;
+// \\ i <<= 2;
+// \\ i >>= 2;
+// \\ i &= 2;
+// \\ i *= 2;
+// \\ i *%= 2;
+// \\ i -= 2;
+// \\ i -%= 2;
+// \\ i += 2;
+// \\ i +%= 2;
+// \\ i /= 2;
+// \\ i %= 2;
+// \\ _ = i == i;
+// \\ _ = i != i;
+// \\ _ = i != i;
+// \\ _ = i.i;
+// \\ _ = i || i;
+// \\ _ = i!i;
+// \\ _ = i ** i;
+// \\ _ = i ++ i;
+// \\ _ = i orelse i;
+// \\ _ = i % i;
+// \\ _ = i / i;
+// \\ _ = i *% i;
+// \\ _ = i * i;
+// \\ _ = i -% i;
+// \\ _ = i - i;
+// \\ _ = i +% i;
+// \\ _ = i + i;
+// \\ _ = i << i;
+// \\ _ = i >> i;
+// \\ _ = i & i;
+// \\ _ = i ^ i;
+// \\ _ = i | i;
+// \\ _ = i >= i;
+// \\ _ = i <= i;
+// \\ _ = i > i;
+// \\ _ = i < i;
+// \\ _ = i and i;
+// \\ _ = i or i;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: precedence" {
+// try testCanonical(
+// \\test "precedence" {
+// \\ a!b();
+// \\ (a!b)();
+// \\ !a!b;
+// \\ !(a!b);
+// \\ !a{};
+// \\ !(a{});
+// \\ a + b{};
+// \\ (a + b){};
+// \\ a << b + c;
+// \\ (a << b) + c;
+// \\ a & b << c;
+// \\ (a & b) << c;
+// \\ a ^ b & c;
+// \\ (a ^ b) & c;
+// \\ a | b ^ c;
+// \\ (a | b) ^ c;
+// \\ a == b | c;
+// \\ (a == b) | c;
+// \\ a and b == c;
+// \\ (a and b) == c;
+// \\ a or b and c;
+// \\ (a or b) and c;
+// \\ (a or b) and c;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: prefix operators" {
+// try testCanonical(
+// \\test "prefix operators" {
+// \\ try return --%~!&0;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: call expression" {
+// try testCanonical(
+// \\test "test calls" {
+// \\ a();
+// \\ a(1);
+// \\ a(1, 2);
+// \\ a(1, 2) + a(1, 2);
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: anytype type" {
+// try testCanonical(
+// \\fn print(args: anytype) anytype {}
+// \\
+// );
+//}
+//
+//test "zig fmt: functions" {
+// try testCanonical(
+// \\extern fn puts(s: *const u8) c_int;
+// \\extern "c" fn puts(s: *const u8) c_int;
+// \\export fn puts(s: *const u8) c_int;
+// \\inline fn puts(s: *const u8) c_int;
+// \\noinline fn puts(s: *const u8) c_int;
+// \\pub extern fn puts(s: *const u8) c_int;
+// \\pub extern "c" fn puts(s: *const u8) c_int;
+// \\pub export fn puts(s: *const u8) c_int;
+// \\pub inline fn puts(s: *const u8) c_int;
+// \\pub noinline fn puts(s: *const u8) c_int;
+// \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
+// \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
+// \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
+// \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
+// \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
+// \\
+// );
+//}
+//
+//test "zig fmt: multiline string" {
+// try testCanonical(
+// \\test "" {
+// \\ const s1 =
+// \\ \\one
+// \\ \\two)
+// \\ \\three
+// \\ ;
+// \\ const s3 = // hi
+// \\ \\one
+// \\ \\two)
+// \\ \\three
+// \\ ;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: values" {
+// try testCanonical(
+// \\test "values" {
+// \\ 1;
+// \\ 1.0;
+// \\ "string";
+// \\ 'c';
+// \\ true;
+// \\ false;
+// \\ null;
+// \\ undefined;
+// \\ anyerror;
+// \\ this;
+// \\ unreachable;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: indexing" {
+// try testCanonical(
+// \\test "test index" {
+// \\ a[0];
+// \\ a[0 + 5];
+// \\ a[0..];
+// \\ a[0..5];
+// \\ a[a[0]];
+// \\ a[a[0..]];
+// \\ a[a[0..5]];
+// \\ a[a[0]..];
+// \\ a[a[0..5]..];
+// \\ a[a[0]..a[0]];
+// \\ a[a[0..5]..a[0]];
+// \\ a[a[0..5]..a[0..5]];
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: struct declaration" {
+// try testCanonical(
+// \\const S = struct {
+// \\ const Self = @This();
+// \\ f1: u8,
+// \\ f3: u8,
+// \\
+// \\ f2: u8,
+// \\
+// \\ fn method(self: *Self) Self {
+// \\ return self.*;
+// \\ }
+// \\};
+// \\
+// \\const Ps = packed struct {
+// \\ a: u8,
+// \\ b: u8,
+// \\
+// \\ c: u8,
+// \\};
+// \\
+// \\const Es = extern struct {
+// \\ a: u8,
+// \\ b: u8,
+// \\
+// \\ c: u8,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: enum declaration" {
+// try testCanonical(
+// \\const E = enum {
+// \\ Ok,
+// \\ SomethingElse = 0,
+// \\};
+// \\
+// \\const E2 = enum(u8) {
+// \\ Ok,
+// \\ SomethingElse = 255,
+// \\ SomethingThird,
+// \\};
+// \\
+// \\const Ee = extern enum {
+// \\ Ok,
+// \\ SomethingElse,
+// \\ SomethingThird,
+// \\};
+// \\
+// \\const Ep = packed enum {
+// \\ Ok,
+// \\ SomethingElse,
+// \\ SomethingThird,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: union declaration" {
+// try testCanonical(
+// \\const U = union {
+// \\ Int: u8,
+// \\ Float: f32,
+// \\ None,
+// \\ Bool: bool,
+// \\};
+// \\
+// \\const Ue = union(enum) {
+// \\ Int: u8,
+// \\ Float: f32,
+// \\ None,
+// \\ Bool: bool,
+// \\};
+// \\
+// \\const E = enum {
+// \\ Int,
+// \\ Float,
+// \\ None,
+// \\ Bool,
+// \\};
+// \\
+// \\const Ue2 = union(E) {
+// \\ Int: u8,
+// \\ Float: f32,
+// \\ None,
+// \\ Bool: bool,
+// \\};
+// \\
+// \\const Eu = extern union {
+// \\ Int: u8,
+// \\ Float: f32,
+// \\ None,
+// \\ Bool: bool,
+// \\};
+// \\
+// );
+//}
+//
+//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: catch" {
+// try testCanonical(
+// \\test "catch" {
+// \\ const a: anyerror!u8 = 0;
+// \\ _ = a catch return;
+// \\ _ = a catch |err| return;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: blocks" {
+// try testCanonical(
+// \\test "blocks" {
+// \\ {
+// \\ const a = 0;
+// \\ const b = 0;
+// \\ }
+// \\
+// \\ blk: {
+// \\ const a = 0;
+// \\ const b = 0;
+// \\ }
+// \\
+// \\ const r = blk: {
+// \\ const a = 0;
+// \\ const b = 0;
+// \\ };
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: switch" {
+// try testCanonical(
+// \\test "switch" {
+// \\ switch (0) {
+// \\ 0 => {},
+// \\ 1 => unreachable,
+// \\ 2, 3 => {},
+// \\ 4...7 => {},
+// \\ 1 + 4 * 3 + 22 => {},
+// \\ else => {
+// \\ const a = 1;
+// \\ const b = a;
+// \\ },
+// \\ }
+// \\
+// \\ const res = switch (0) {
+// \\ 0 => 0,
+// \\ 1 => 2,
+// \\ 1 => a = 4,
+// \\ else => 4,
+// \\ };
+// \\
+// \\ const Union = union(enum) {
+// \\ Int: i64,
+// \\ Float: f64,
+// \\ };
+// \\
+// \\ switch (u) {
+// \\ Union.Int => |int| {},
+// \\ Union.Float => |*float| unreachable,
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: while" {
+// try testCanonical(
+// \\test "while" {
+// \\ while (10 < 1) unreachable;
+// \\
+// \\ while (10 < 1) unreachable else unreachable;
+// \\
+// \\ while (10 < 1) {
+// \\ unreachable;
+// \\ }
+// \\
+// \\ while (10 < 1)
+// \\ unreachable;
+// \\
+// \\ var i: usize = 0;
+// \\ while (i < 10) : (i += 1) {
+// \\ continue;
+// \\ }
+// \\
+// \\ i = 0;
+// \\ while (i < 10) : (i += 1)
+// \\ continue;
+// \\
+// \\ i = 0;
+// \\ var j: usize = 0;
+// \\ while (i < 10) : ({
+// \\ i += 1;
+// \\ j += 1;
+// \\ }) {
+// \\ continue;
+// \\ }
+// \\
+// \\ var a: ?u8 = 2;
+// \\ while (a) |v| : (a = null) {
+// \\ continue;
+// \\ }
+// \\
+// \\ while (a) |v| : (a = null)
+// \\ unreachable;
+// \\
+// \\ label: while (10 < 0) {
+// \\ unreachable;
+// \\ }
+// \\
+// \\ const res = while (0 < 10) {
+// \\ break 7;
+// \\ } else {
+// \\ unreachable;
+// \\ };
+// \\
+// \\ const res = while (0 < 10)
+// \\ break 7
+// \\ else
+// \\ unreachable;
+// \\
+// \\ var a: anyerror!u8 = 0;
+// \\ while (a) |v| {
+// \\ a = error.Err;
+// \\ } else |err| {
+// \\ i = 1;
+// \\ }
+// \\
+// \\ comptime var k: usize = 0;
+// \\ inline while (i < 10) : (i += 1)
+// \\ j += 2;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: for" {
+// try testCanonical(
+// \\test "for" {
+// \\ for (a) |v| {
+// \\ continue;
+// \\ }
+// \\
+// \\ for (a) |v| continue;
+// \\
+// \\ for (a) |v| continue else return;
+// \\
+// \\ for (a) |v| {
+// \\ continue;
+// \\ } else return;
+// \\
+// \\ for (a) |v| continue else {
+// \\ return;
+// \\ }
+// \\
+// \\ for (a) |v|
+// \\ continue
+// \\ else
+// \\ return;
+// \\
+// \\ for (a) |v|
+// \\ continue;
+// \\
+// \\ for (a) |*v|
+// \\ continue;
+// \\
+// \\ for (a) |v, i| {
+// \\ continue;
+// \\ }
+// \\
+// \\ for (a) |v, i|
+// \\ continue;
+// \\
+// \\ for (a) |b| switch (b) {
+// \\ c => {},
+// \\ d => {},
+// \\ };
+// \\
+// \\ for (a) |b|
+// \\ switch (b) {
+// \\ c => {},
+// \\ d => {},
+// \\ };
+// \\
+// \\ const res = for (a) |v, i| {
+// \\ break v;
+// \\ } else {
+// \\ unreachable;
+// \\ };
+// \\
+// \\ var num: usize = 0;
+// \\ inline for (a) |v, i| {
+// \\ num += v;
+// \\ num += i;
+// \\ }
+// \\}
+// \\
+// );
+//
+// try testTransform(
+// \\test "fix for" {
+// \\ for (a) |x|
+// \\ f(x) else continue;
+// \\}
+// \\
+// ,
+// \\test "fix for" {
+// \\ for (a) |x|
+// \\ f(x)
+// \\ else continue;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: if" {
+// try testCanonical(
+// \\test "if" {
+// \\ if (10 < 0) {
+// \\ unreachable;
+// \\ }
+// \\
+// \\ if (10 < 0) unreachable;
+// \\
+// \\ if (10 < 0) {
+// \\ unreachable;
+// \\ } else {
+// \\ const a = 20;
+// \\ }
+// \\
+// \\ if (10 < 0) {
+// \\ unreachable;
+// \\ } else if (5 < 0) {
+// \\ unreachable;
+// \\ } else {
+// \\ const a = 20;
+// \\ }
+// \\
+// \\ const is_world_broken = if (10 < 0) true else false;
+// \\ const some_number = 1 + if (10 < 0) 2 else 3;
+// \\
+// \\ const a: ?u8 = 10;
+// \\ const b: ?u8 = null;
+// \\ if (a) |v| {
+// \\ const some = v;
+// \\ } else if (b) |*v| {
+// \\ unreachable;
+// \\ } else {
+// \\ const some = 10;
+// \\ }
+// \\
+// \\ const non_null_a = if (a) |v| v else 0;
+// \\
+// \\ const a_err: anyerror!u8 = 0;
+// \\ if (a_err) |v| {
+// \\ const p = v;
+// \\ } else |err| {
+// \\ unreachable;
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: defer" {
+// try testCanonical(
+// \\test "defer" {
+// \\ var i: usize = 0;
+// \\ defer i = 1;
+// \\ defer {
+// \\ i += 2;
+// \\ i *= i;
+// \\ }
+// \\
+// \\ errdefer i += 3;
+// \\ errdefer {
+// \\ i += 2;
+// \\ i /= i;
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: comptime" {
+// try testCanonical(
+// \\fn a() u8 {
+// \\ return 5;
+// \\}
+// \\
+// \\fn b(comptime i: u8) u8 {
+// \\ return i;
+// \\}
+// \\
+// \\const av = comptime a();
+// \\const av2 = comptime blk: {
+// \\ var res = a();
+// \\ res *= b(2);
+// \\ break :blk res;
+// \\};
+// \\
+// \\comptime {
+// \\ _ = a();
+// \\}
+// \\
+// \\test "comptime" {
+// \\ const av3 = comptime a();
+// \\ const av4 = comptime blk: {
+// \\ var res = a();
+// \\ res *= a();
+// \\ break :blk res;
+// \\ };
+// \\
+// \\ comptime var i = 0;
+// \\ comptime {
+// \\ i = a();
+// \\ i += b(i);
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: fn type" {
+// try testCanonical(
+// \\fn a(i: u8) u8 {
+// \\ return i + 1;
+// \\}
+// \\
+// \\const a: fn (u8) u8 = undefined;
+// \\const b: fn (u8) callconv(.Naked) u8 = undefined;
+// \\const ap: fn (u8) u8 = a;
+// \\
+// );
+//}
+//
+//test "zig fmt: inline asm" {
+// try testCanonical(
+// \\pub fn syscall1(number: usize, arg1: usize) usize {
+// \\ return asm volatile ("syscall"
+// \\ : [ret] "={rax}" (-> usize)
+// \\ : [number] "{rax}" (number),
+// \\ [arg1] "{rdi}" (arg1)
+// \\ : "rcx", "r11"
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: async functions" {
+// try testCanonical(
+// \\fn simpleAsyncFn() void {
+// \\ const a = async a.b();
+// \\ x += 1;
+// \\ suspend;
+// \\ x += 1;
+// \\ suspend;
+// \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
+// \\ await p;
+// \\}
+// \\
+// \\test "suspend, resume, await" {
+// \\ const p: anyframe = async testAsyncSeq();
+// \\ resume p;
+// \\ await p;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: nosuspend" {
+// try testCanonical(
+// \\const a = nosuspend foo();
+// \\
+// );
+//}
+//
+//test "zig fmt: Block after if" {
+// try testCanonical(
+// \\test "Block after if" {
+// \\ if (true) {
+// \\ const a = 0;
+// \\ }
+// \\
+// \\ {
+// \\ const a = 0;
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: use" {
+// try testCanonical(
+// \\usingnamespace @import("std");
+// \\pub usingnamespace @import("std");
+// \\
+// );
+//}
+//
+//test "zig fmt: string identifier" {
+// try testCanonical(
+// \\const @"a b" = @"c d".@"e f";
+// \\fn @"g h"() void {}
+// \\
+// );
+//}
+//
+//test "zig fmt: error return" {
+// try testCanonical(
+// \\fn err() anyerror {
+// \\ call();
+// \\ return error.InvalidArgs;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: comptime block in container" {
+// try testCanonical(
+// \\pub fn container() type {
+// \\ return struct {
+// \\ comptime {
+// \\ if (false) {
+// \\ unreachable;
+// \\ }
+// \\ }
+// \\ };
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: inline asm parameter alignment" {
+// try testCanonical(
+// \\pub fn main() void {
+// \\ asm volatile (
+// \\ \\ foo
+// \\ \\ bar
+// \\ );
+// \\ asm volatile (
+// \\ \\ foo
+// \\ \\ bar
+// \\ : [_] "" (-> usize),
+// \\ [_] "" (-> usize)
+// \\ );
+// \\ asm volatile (
+// \\ \\ foo
+// \\ \\ bar
+// \\ :
+// \\ : [_] "" (0),
+// \\ [_] "" (0)
+// \\ );
+// \\ asm volatile (
+// \\ \\ foo
+// \\ \\ bar
+// \\ :
+// \\ :
+// \\ : "", ""
+// \\ );
+// \\ asm volatile (
+// \\ \\ foo
+// \\ \\ bar
+// \\ : [_] "" (-> usize),
+// \\ [_] "" (-> usize)
+// \\ : [_] "" (0),
+// \\ [_] "" (0)
+// \\ : "", ""
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: multiline string in array" {
+// try testCanonical(
+// \\const Foo = [][]const u8{
+// \\ \\aaa
+// \\ ,
+// \\ \\bbb
+// \\};
+// \\
+// \\fn bar() void {
+// \\ const Foo = [][]const u8{
+// \\ \\aaa
+// \\ ,
+// \\ \\bbb
+// \\ };
+// \\ const Bar = [][]const u8{ // comment here
+// \\ \\aaa
+// \\ \\
+// \\ , // and another comment can go here
+// \\ \\bbb
+// \\ };
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: if type expr" {
+// try testCanonical(
+// \\const mycond = true;
+// \\pub fn foo() if (mycond) i32 else void {
+// \\ if (mycond) {
+// \\ return 42;
+// \\ }
+// \\}
+// \\
+// );
+//}
+//test "zig fmt: file ends with struct field" {
+// try testCanonical(
+// \\a: bool
+// \\
+// );
+//}
+//
+//test "zig fmt: comment after empty comment" {
+// try testTransform(
+// \\const x = true; //
+// \\//
+// \\//
+// \\//a
+// \\
+// ,
+// \\const x = true;
+// \\//a
+// \\
+// );
+//}
+//
+//test "zig fmt: line comment in array" {
+// try testTransform(
+// \\test "a" {
+// \\ var arr = [_]u32{
+// \\ 0
+// \\ // 1,
+// \\ // 2,
+// \\ };
+// \\}
+// \\
+// ,
+// \\test "a" {
+// \\ var arr = [_]u32{
+// \\ 0, // 1,
+// \\ // 2,
+// \\ };
+// \\}
+// \\
+// );
+// try testCanonical(
+// \\test "a" {
+// \\ var arr = [_]u32{
+// \\ 0,
+// \\ // 1,
+// \\ // 2,
+// \\ };
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: comment after params" {
+// try testTransform(
+// \\fn a(
+// \\ b: u32
+// \\ // c: u32,
+// \\ // d: u32,
+// \\) void {}
+// \\
+// ,
+// \\fn a(
+// \\ b: u32, // c: u32,
+// \\ // d: u32,
+// \\) void {}
+// \\
+// );
+// try testCanonical(
+// \\fn a(
+// \\ b: u32,
+// \\ // c: u32,
+// \\ // d: u32,
+// \\) void {}
+// \\
+// );
+//}
+//
+//test "zig fmt: comment in array initializer/access" {
+// try testCanonical(
+// \\test "a" {
+// \\ var a = x{ //aa
+// \\ //bb
+// \\ };
+// \\ var a = []x{ //aa
+// \\ //bb
+// \\ };
+// \\ var b = [ //aa
+// \\ _
+// \\ ]x{ //aa
+// \\ //bb
+// \\ 9,
+// \\ };
+// \\ var c = b[ //aa
+// \\ 0
+// \\ ];
+// \\ var d = [_
+// \\ //aa
+// \\ ]x{ //aa
+// \\ //bb
+// \\ 9,
+// \\ };
+// \\ var e = d[0
+// \\ //aa
+// \\ ];
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: comments at several places in struct init" {
+// try testTransform(
+// \\var bar = Bar{
+// \\ .x = 10, // test
+// \\ .y = "test"
+// \\ // test
+// \\};
+// \\
+// ,
+// \\var bar = Bar{
+// \\ .x = 10, // test
+// \\ .y = "test", // test
+// \\};
+// \\
+// );
+//
+// try testCanonical(
+// \\var bar = Bar{ // test
+// \\ .x = 10, // test
+// \\ .y = "test",
+// \\ // test
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: top level doc comments" {
+// try testCanonical(
+// \\//! tld 1
+// \\//! tld 2
+// \\//! tld 3
+// \\
+// \\// comment
+// \\
+// \\/// A doc
+// \\const A = struct {
+// \\ //! A tld 1
+// \\ //! A tld 2
+// \\ //! A tld 3
+// \\};
+// \\
+// \\/// B doc
+// \\const B = struct {
+// \\ //! B tld 1
+// \\ //! B tld 2
+// \\ //! B tld 3
+// \\
+// \\ /// b doc
+// \\ b: u32,
+// \\};
+// \\
+// \\/// C doc
+// \\const C = struct {
+// \\ //! C tld 1
+// \\ //! C tld 2
+// \\ //! C tld 3
+// \\
+// \\ /// c1 doc
+// \\ c1: u32,
+// \\
+// \\ //! C tld 4
+// \\ //! C tld 5
+// \\ //! C tld 6
+// \\
+// \\ /// c2 doc
+// \\ c2: u32,
+// \\};
+// \\
+// );
+// try testCanonical(
+// \\//! Top-level documentation.
+// \\
+// \\/// This is A
+// \\pub const A = usize;
+// \\
+// );
+// try testCanonical(
+// \\//! Nothing here
+// \\
+// );
+//}
+//
+//test "zig fmt: extern without container keyword returns error" {
+// try testError(
+// \\const container = extern {};
+// \\
+// , &[_]Error{
+// .ExpectedExpr,
+// .ExpectedVarDeclOrFn,
+// });
+//}
+//
+//test "zig fmt: integer literals with underscore separators" {
+// try testTransform(
+// \\const
+// \\ x =
+// \\ 1_234_567
+// \\ +(0b0_1-0o7_0+0xff_FF ) + 0_0;
+// ,
+// \\const x =
+// \\ 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 0_0;
+// \\
+// );
+//}
+//
+//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: 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: convert async fn into callconv(.Async)" {
+// try testTransform(
+// \\async fn foo() void {}
+// ,
+// \\fn foo() callconv(.Async) void {}
+// \\
+// );
+//}
+//
+//test "zig fmt: convert extern fn proto into callconv(.C)" {
+// try testTransform(
+// \\extern fn foo0() void {}
+// \\const foo1 = extern fn () void;
+// ,
+// \\extern fn foo0() void {}
+// \\const foo1 = fn () callconv(.C) void;
+// \\
+// );
+//}
+//
+//test "zig fmt: C var args" {
+// try testCanonical(
+// \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
+// \\
+// );
+//}
+//
+//test "zig fmt: Only indent multiline string literals in function calls" {
+// try testCanonical(
+// \\test "zig fmt:" {
+// \\ try testTransform(
+// \\ \\const X = struct {
+// \\ \\ foo: i32, bar: i8 };
+// \\ ,
+// \\ \\const X = struct {
+// \\ \\ foo: i32, bar: i8
+// \\ \\};
+// \\ \\
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: Don't add extra newline after if" {
+// try testCanonical(
+// \\pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: []const u8) !void {
+// \\ if (cwd().symLink(existing_path, new_path, .{})) {
+// \\ return;
+// \\ }
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: comments in ternary ifs" {
+// try testCanonical(
+// \\const x = if (true) {
+// \\ 1;
+// \\} else if (false)
+// \\ // Comment
+// \\ 0;
+// \\const y = if (true)
+// \\ // Comment
+// \\ 1
+// \\else
+// \\ 0;
+// \\
+// \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
+// \\
+// );
+//}
+//
+//test "zig fmt: test comments in field access chain" {
+// try testCanonical(
+// \\pub const str = struct {
+// \\ pub const Thing = more.more //
+// \\ .more() //
+// \\ .more().more() //
+// \\ .more() //
+// \\ // .more() //
+// \\ .more() //
+// \\ .more();
+// \\ data: Data,
+// \\};
+// \\
+// \\pub const str = struct {
+// \\ pub const Thing = more.more //
+// \\ .more() //
+// \\ // .more() //
+// \\ // .more() //
+// \\ // .more() //
+// \\ .more() //
+// \\ .more();
+// \\ data: Data,
+// \\};
+// \\
+// \\pub const str = struct {
+// \\ pub const Thing = more //
+// \\ .more //
+// \\ .more() //
+// \\ .more();
+// \\ data: Data,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
+// try testCanonical(
+// \\fn foo() void {
+// \\ z.display_message_dialog(
+// \\ *const [323:0]u8,
+// \\ \\Message Text
+// \\ \\------------
+// \\ \\xxxxxxxxxxxx
+// \\ \\xxxxxxxxxxxx
+// \\ ,
+// \\ g.GtkMessageType.GTK_MESSAGE_WARNING,
+// \\ null,
+// \\ );
+// \\
+// \\ z.display_message_dialog(*const [323:0]u8,
+// \\ \\Message Text
+// \\ \\------------
+// \\ \\xxxxxxxxxxxx
+// \\ \\xxxxxxxxxxxx
+// \\ , g.GtkMessageType.GTK_MESSAGE_WARNING, null);
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: Control flow statement as body of blockless if" {
+// try testCanonical(
+// \\pub fn main() void {
+// \\ const zoom_node = if (focused_node == layout_first)
+// \\ if (it.next()) {
+// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+// \\ } else null
+// \\ else
+// \\ focused_node;
+// \\
+// \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
+// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+// \\ } else null else
+// \\ focused_node;
+// \\
+// \\ const zoom_node = if (focused_node == layout_first)
+// \\ if (it.next()) {
+// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+// \\ } else null;
+// \\
+// \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
+// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+// \\ };
+// \\
+// \\ const zoom_node = if (focused_node == layout_first) for (nodes) |node| {
+// \\ break node;
+// \\ };
+// \\
+// \\ const zoom_node = if (focused_node == layout_first) switch (nodes) {
+// \\ 0 => 0,
+// \\ } else
+// \\ focused_node;
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: " {
+// try testCanonical(
+// \\pub fn sendViewTags(self: Self) void {
+// \\ var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));
+// \\ while (it.next()) |node|
+// \\ view_tags.append(node.view.current_tags) catch {
+// \\ c.wl_resource_post_no_memory(self.wl_resource);
+// \\ log.crit(.river_status, "out of memory", .{});
+// \\ return;
+// \\ };
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: allow trailing line comments to do manual array formatting" {
+// try testCanonical(
+// \\fn foo() void {
+// \\ self.code.appendSliceAssumeCapacity(&[_]u8{
+// \\ 0x55, // push rbp
+// \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
+// \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
+// \\ });
+// \\
+// \\ di_buf.appendAssumeCapacity(&[_]u8{
+// \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header
+// \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs
+// \\ DW.AT_low_pc, DW_FORM_addr,
+// \\ DW.AT_high_pc, DW_FORM_addr,
+// \\ DW.AT_name, DW_FORM_strp,
+// \\ DW.AT_comp_dir, DW_FORM_strp,
+// \\ DW.AT_producer, DW_FORM_strp,
+// \\ DW.AT_language, DW_FORM_data2,
+// \\ 0, 0, // sentinel
+// \\ });
+// \\
+// \\ self.code.appendSliceAssumeCapacity(&[_]u8{
+// \\ 0x55, // push rbp
+// \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
+// \\ // How do we handle this?
+// \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
+// \\ // Here's a blank line, should that be allowed?
+// \\
+// \\ 0x48, 0x89, 0xe5,
+// \\ 0x33, 0x45,
+// \\ // Now the comment breaks a single line -- how do we handle this?
+// \\ 0x88,
+// \\ });
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: multiline string literals should play nice with array initializers" {
+// try testCanonical(
+// \\fn main() void {
+// \\ var a = .{.{.{.{.{.{.{.{
+// \\ 0,
+// \\ }}}}}}}};
+// \\ myFunc(.{
+// \\ "aaaaaaa", "bbbbbb", "ccccc",
+// \\ "dddd", ("eee"), ("fff"),
+// \\ ("gggg"),
+// \\ // Line comment
+// \\ \\Multiline String Literals can be quite long
+// \\ ,
+// \\ \\Multiline String Literals can be quite long
+// \\ \\Multiline String Literals can be quite long
+// \\ ,
+// \\ \\Multiline String Literals can be quite long
+// \\ \\Multiline String Literals can be quite long
+// \\ \\Multiline String Literals can be quite long
+// \\ \\Multiline String Literals can be quite long
+// \\ ,
+// \\ (
+// \\ \\Multiline String Literals can be quite long
+// \\ ),
+// \\ .{
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ },
+// \\ .{(
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ )},
+// \\ .{
+// \\ "xxxxxxx", "xxx",
+// \\ (
+// \\ \\ xxx
+// \\ ),
+// \\ "xxx", "xxx",
+// \\ },
+// \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" }, .{ "xxxxxxx", "xxx", "xxx", "xxx" },
+// \\ "aaaaaaa", "bbbbbb", "ccccc", // -
+// \\ "dddd", ("eee"), ("fff"),
+// \\ .{
+// \\ "xxx", "xxx",
+// \\ (
+// \\ \\ xxx
+// \\ ),
+// \\ "xxxxxxxxxxxxxx", "xxx",
+// \\ },
+// \\ .{
+// \\ (
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ ),
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ },
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+// \\ });
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: use of comments and Multiline string literals may force the parameters over multiple lines" {
+// try testCanonical(
+// \\pub fn makeMemUndefined(qzz: []u8) i1 {
+// \\ cases.add( // fixed bug #2032
+// \\ "compile diagnostic string for top level decl type",
+// \\ \\export fn entry() void {
+// \\ \\ var foo: u32 = @This(){};
+// \\ \\}
+// \\ , &[_][]const u8{
+// \\ "tmp.zig:2:27: error: type 'u32' does not support array initialization",
+// \\ });
+// \\ @compileError(
+// \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
+// \\ \\ Consider providing your own hash function.
+// \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
+// \\ \\ Consider providing your own hash function.
+// \\ );
+// \\ return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
+// \\ .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
+// \\}
+// \\
+// \\// This looks like garbage don't do this
+// \\const rparen = tree.prevToken(
+// \\// the first token for the annotation expressions is the left
+// \\// parenthesis, hence the need for two prevToken
+// \\ if (fn_proto.getAlignExpr()) |align_expr|
+// \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))
+// \\else if (fn_proto.getSectionExpr()) |section_expr|
+// \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))
+// \\else if (fn_proto.getCallconvExpr()) |callconv_expr|
+// \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
+// \\else switch (fn_proto.return_type) {
+// \\ .Explicit => |node| node.firstToken(),
+// \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),
+// \\ .Invalid => unreachable,
+// \\});
+// \\
+// );
+//}
+//
+//test "zig fmt: single argument trailing commas in @builtins()" {
+// try testCanonical(
+// \\pub fn foo(qzz: []u8) i1 {
+// \\ @panic(
+// \\ foo,
+// \\ );
+// \\ panic(
+// \\ foo,
+// \\ );
+// \\ @panic(
+// \\ foo,
+// \\ bar,
+// \\ );
+// \\}
+// \\
+// );
+//}
+//
+//test "zig fmt: trailing comma should force multiline 1 column" {
+// try testTransform(
+// \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
+// \\
+// ,
+// \\pub const UUID_NULL: uuid_t = [16]u8{
+// \\ 0,
+// \\ 0,
+// \\ 0,
+// \\ 0,
+// \\};
+// \\
+// );
+//}
+//
+//test "zig fmt: function params should align nicely" {
+// try testCanonical(
+// \\pub fn foo() void {
+// \\ cases.addRuntimeSafety("slicing operator with sentinel",
+// \\ \\const std = @import("std");
+// \\ ++ check_panic_msg ++
+// \\ \\pub fn main() void {
+// \\ \\ var buf = [4]u8{'a','b','c',0};
+// \\ \\ const slice = buf[0..:0];
+// \\ \\}
+// \\ );
+// \\}
+// \\
+// );
+//}
const std = @import("std");
const mem = std.mem;
@@ -3763,8 +3740,10 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
errdefer buffer.deinit();
const writer = buffer.writer();
- anything_changed.* = try std.zig.render(allocator, writer, tree);
- return buffer.toOwnedSlice();
+ try std.zig.render(allocator, writer, tree);
+ const result = buffer.toOwnedSlice();
+ anything_changed.* = !mem.eql(u8, result, source);
+ return result;
}
fn testTransform(source: []const u8, expected_source: []const u8) !void {
const needed_alloc_count = x: {
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
index c8568301ea..17c59776b5 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -14,2167 +14,2072 @@ const indent_delta = 4;
const asm_indent_delta = 2;
pub const Error = error{
- /// Ran out of memory allocating call stack frames to complete rendering.
+ /// Ran out of memory allocating call stack frames to complete rendering, or
+ /// ran out of memory allocating space in the output buffer.
OutOfMemory,
};
-/// Returns whether anything changed
-pub fn render(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tree) (@TypeOf(stream).Error || Error)!bool {
- // cannot render an invalid tree
- std.debug.assert(tree.errors.len == 0);
+const Writer = std.ArrayList(u8).Writer;
+const Ais = std.io.AutoIndentingStream(Writer);
- var change_detection_stream = std.io.changeDetectionStream(tree.source, stream);
- var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, change_detection_stream.writer());
-
- try renderRoot(allocator, &auto_indenting_stream, tree);
-
- return change_detection_stream.changeDetected();
+/// Returns whether anything changed.
+/// `gpa` is used for allocating extra stack memory if needed, because
+/// this function utilizes recursion.
+pub fn render(gpa: *mem.Allocator, writer: Writer, tree: ast.Tree) Error!void {
+ assert(tree.errors.len == 0); // cannot render an invalid tree
+ var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, writer);
+ try renderRoot(&auto_indenting_stream, tree);
}
-fn renderRoot(
- allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
-) (@TypeOf(ais.*).Error || Error)!void {
-
- // render all the line comments at the beginning of the file
- for (tree.token_ids) |token_id, i| {
- if (token_id != .LineComment) break;
- const token_loc = tree.token_locs[i];
- try ais.writer().print("{s}\n", .{mem.trimRight(u8, tree.tokenSliceLoc(token_loc), " ")});
- const next_token = tree.token_locs[i + 1];
- const loc = tree.tokenLocationLoc(token_loc.end, next_token);
- if (loc.line >= 2) {
- try ais.insertNewline();
- }
- }
-
- var decl_i: ast.NodeIndex = 0;
- const root_decls = tree.root_node.decls();
-
- if (root_decls.len == 0) return;
+/// 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 {
+ var index: usize = start;
+ var count: usize = 0;
while (true) {
- var decl = root_decls[decl_i];
-
- // This loop does the following:
- //
- // - Iterates through line/doc comment tokens that precedes the current
- // decl.
- // - Figures out the first token index (`copy_start_token_index`) which
- // hasn't been copied to the output stream yet.
- // - Detects `zig fmt: (off|on)` in the line comment tokens, and
- // determines whether the current decl should be reformatted or not.
- //
- var token_index = decl.firstToken();
- var fmt_active = true;
- var found_fmt_directive = false;
-
- var copy_start_token_index = token_index;
-
- while (token_index != 0) {
- token_index -= 1;
- const token_id = tree.token_ids[token_index];
- switch (token_id) {
- .LineComment => {},
- .DocComment => {
- copy_start_token_index = token_index;
- continue;
- },
- else => break,
- }
-
- const token_loc = tree.token_locs[token_index];
- if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: off")) {
- if (!found_fmt_directive) {
- fmt_active = false;
- found_fmt_directive = true;
- }
- } else if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: on")) {
- if (!found_fmt_directive) {
- fmt_active = true;
- found_fmt_directive = true;
- }
+ // Scan forward to the next line comment, counting newlines.
+ const comment_start = mem.indexOf(u8, tree.source[index..end], "//") orelse return count;
+ const newline = mem.indexOfScalar(u8, tree.source[comment_start..end], '\n').?;
+ const untrimmed_comment = tree.source[comment_start..][0..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();
}
}
+ try ais.writer().print("{s}\n", .{trimmed_comment});
+ index += comment_start + newline;
+ }
+}
- if (!fmt_active) {
- // Reformatting is disabled for the current decl and possibly some
- // more decls that follow.
- // Find the next `decl` for which reformatting is re-enabled.
- token_index = decl.firstToken();
-
- while (!fmt_active) {
- decl_i += 1;
- if (decl_i >= root_decls.len) {
- // If there's no next reformatted `decl`, just copy the
- // remaining input tokens and bail out.
- const start = tree.token_locs[copy_start_token_index].start;
- try copyFixingWhitespace(ais, tree.source[start..]);
- return;
- }
- decl = root_decls[decl_i];
- var decl_first_token_index = decl.firstToken();
-
- while (token_index < decl_first_token_index) : (token_index += 1) {
- const token_id = tree.token_ids[token_index];
- switch (token_id) {
- .LineComment => {},
- .Eof => unreachable,
- else => continue,
- }
- const token_loc = tree.token_locs[token_index];
- if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: on")) {
- fmt_active = true;
- } else if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: off")) {
- fmt_active = false;
- }
- }
- }
-
- // Found the next `decl` for which reformatting is enabled. Copy
- // the input tokens before the `decl` that haven't been copied yet.
- var copy_end_token_index = decl.firstToken();
- token_index = copy_end_token_index;
- while (token_index != 0) {
- token_index -= 1;
- const token_id = tree.token_ids[token_index];
- switch (token_id) {
- .LineComment => {},
- .DocComment => {
- copy_end_token_index = token_index;
- continue;
- },
- else => break,
- }
- }
+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, "");
- const start = tree.token_locs[copy_start_token_index].start;
- const end = tree.token_locs[copy_end_token_index].start;
- try copyFixingWhitespace(ais, tree.source[start..end]);
- }
+ // 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];
+ if (root_decls.len == 0) return;
- try renderTopLevelDecl(allocator, ais, tree, decl);
- decl_i += 1;
- if (decl_i >= root_decls.len) return;
- try renderExtraNewline(tree, ais, root_decls[decl_i]);
+ for (root_decls) |decl| {
+ try renderTopLevelDecl(ais, tree, decl);
}
}
-fn renderExtraNewline(tree: *ast.Tree, ais: anytype, node: *ast.Node) @TypeOf(ais.*).Error!void {
- return renderExtraNewlineToken(tree, ais, node.firstToken());
+fn renderExtraNewline(tree: ast.Tree, ais: *Ais, node: ast.Node.Index) Error!void {
+ return renderExtraNewlineToken(tree, ais, tree.firstToken(node));
}
-fn renderExtraNewlineToken(
- tree: *ast.Tree,
- ais: anytype,
- first_token: ast.TokenIndex,
-) @TypeOf(ais.*).Error!void {
- var prev_token = first_token;
- if (prev_token == 0) return;
- var newline_threshold: usize = 2;
- while (tree.token_ids[prev_token - 1] == .DocComment) {
- if (tree.tokenLocation(tree.token_locs[prev_token - 1].end, prev_token).line == 1) {
- newline_threshold += 1;
- }
- prev_token -= 1;
- }
- const prev_token_end = tree.token_locs[prev_token - 1].end;
- const loc = tree.tokenLocation(prev_token_end, first_token);
- if (loc.line >= newline_threshold) {
- try ais.insertNewline();
- }
+fn renderExtraNewlineToken(tree: ast.Tree, ais: *Ais, first_token: ast.TokenIndex) Error!void {
+ @panic("TODO implement renderExtraNewlineToken");
+ //var prev_token = first_token;
+ //if (prev_token == 0) return;
+ //const token_tags = tree.tokens.items(.tag);
+ //var newline_threshold: usize = 2;
+ //while (token_tags[prev_token - 1] == .DocComment) {
+ // if (tree.tokenLocation(tree.token_locs[prev_token - 1].end, prev_token).line == 1) {
+ // newline_threshold += 1;
+ // }
+ // prev_token -= 1;
+ //}
+ //const prev_token_end = tree.token_locs[prev_token - 1].end;
+ //const loc = tree.tokenLocation(prev_token_end, first_token);
+ //if (loc.line >= newline_threshold) {
+ // try ais.insertNewline();
+ //}
}
-fn renderTopLevelDecl(allocator: *mem.Allocator, ais: anytype, tree: *ast.Tree, decl: *ast.Node) (@TypeOf(ais.*).Error || Error)!void {
- try renderContainerDecl(allocator, ais, tree, decl, .Newline);
+fn renderTopLevelDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index) Error!void {
+ return renderContainerDecl(ais, tree, decl, .Newline);
}
-fn renderContainerDecl(allocator: *mem.Allocator, ais: anytype, tree: *ast.Tree, decl: *ast.Node, space: Space) (@TypeOf(ais.*).Error || Error)!void {
- switch (decl.tag) {
- .FnProto => {
- const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
-
- try renderDocComments(tree, ais, fn_proto, fn_proto.getDocComments());
-
- if (fn_proto.getBodyNode()) |body_node| {
- try renderExpression(allocator, ais, tree, decl, .Space);
- try renderExpression(allocator, ais, tree, body_node, space);
- } else {
- try renderExpression(allocator, ais, tree, decl, .None);
- try renderToken(tree, ais, tree.nextToken(decl.lastToken()), space);
- }
- },
-
- .Use => {
- const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
-
- if (use_decl.visib_token) |visib_token| {
- try renderToken(tree, ais, visib_token, .Space); // pub
- }
- try renderToken(tree, ais, use_decl.use_token, .Space); // usingnamespace
- try renderExpression(allocator, ais, tree, use_decl.expr, .None);
- try renderToken(tree, ais, use_decl.semicolon_token, space); // ;
- },
-
- .VarDecl => {
- const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
-
- try renderDocComments(tree, ais, var_decl, var_decl.getDocComments());
- try renderVarDecl(allocator, ais, tree, var_decl);
- },
-
- .TestDecl => {
- const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
-
- try renderDocComments(tree, ais, test_decl, test_decl.doc_comments);
- try renderToken(tree, ais, test_decl.test_token, .Space);
- if (test_decl.name) |name|
- try renderExpression(allocator, ais, tree, name, .Space);
- try renderExpression(allocator, ais, tree, test_decl.body_node, space);
- },
-
- .ContainerField => {
- const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
-
- try renderDocComments(tree, ais, field, field.doc_comments);
- if (field.comptime_token) |t| {
- try renderToken(tree, ais, t, .Space); // comptime
- }
-
- const src_has_trailing_comma = blk: {
- const maybe_comma = tree.nextToken(field.lastToken());
- break :blk tree.token_ids[maybe_comma] == .Comma;
- };
-
- // The trailing comma is emitted at the end, but if it's not present
- // we still have to respect the specified `space` parameter
- const last_token_space: Space = if (src_has_trailing_comma) .None else space;
-
- if (field.type_expr == null and field.value_expr == null) {
- try renderToken(tree, ais, field.name_token, last_token_space); // name
- } else if (field.type_expr != null and field.value_expr == null) {
- try renderToken(tree, ais, field.name_token, .None); // name
- try renderToken(tree, ais, tree.nextToken(field.name_token), .Space); // :
-
- if (field.align_expr) |align_value_expr| {
- try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
- const lparen_token = tree.prevToken(align_value_expr.firstToken());
- const align_kw = tree.prevToken(lparen_token);
- const rparen_token = tree.nextToken(align_value_expr.lastToken());
- try renderToken(tree, ais, align_kw, .None); // align
- try renderToken(tree, ais, lparen_token, .None); // (
- try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
- try renderToken(tree, ais, rparen_token, last_token_space); // )
- } else {
- try renderExpression(allocator, ais, tree, field.type_expr.?, last_token_space); // type
- }
- } else if (field.type_expr == null and field.value_expr != null) {
- try renderToken(tree, ais, field.name_token, .Space); // name
- try renderToken(tree, ais, tree.nextToken(field.name_token), .Space); // =
- try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
- } else {
- try renderToken(tree, ais, field.name_token, .None); // name
- try renderToken(tree, ais, tree.nextToken(field.name_token), .Space); // :
-
- if (field.align_expr) |align_value_expr| {
- try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
- const lparen_token = tree.prevToken(align_value_expr.firstToken());
- const align_kw = tree.prevToken(lparen_token);
- const rparen_token = tree.nextToken(align_value_expr.lastToken());
- try renderToken(tree, ais, align_kw, .None); // align
- try renderToken(tree, ais, lparen_token, .None); // (
- try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
- try renderToken(tree, ais, rparen_token, .Space); // )
- } else {
- try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
- }
- try renderToken(tree, ais, tree.prevToken(field.value_expr.?.firstToken()), .Space); // =
- try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
- }
-
- if (src_has_trailing_comma) {
- const comma = tree.nextToken(field.lastToken());
- try renderToken(tree, ais, comma, space);
- }
- },
+fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void {
+ switch (tree.nodes.items(.tag)[decl]) {
+ .UsingNamespace,
+ .FnProtoSimple,
+ .FnProtoSimpleMulti,
+ .FnProtoOne,
+ .FnProto,
+ .FnDecl,
+ .GlobalVarDecl,
+ .LocalVarDecl,
+ .SimpleVarDecl,
+ .AlignedVarDecl,
+ .TestDecl,
+ .ContainerFieldInit,
+ .ContainerFieldAlign,
+ .ContainerField,
+ => @panic("TODO implement renderContainerDecl"),
- .Comptime => {
- assert(!decl.requireSemiColon());
- try renderExpression(allocator, ais, tree, decl, space);
- },
+ .Comptime => return renderExpression(ais, tree, decl, space),
- .DocComment => {
- const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl);
- const kind = tree.token_ids[comment.first_line];
- try renderToken(tree, ais, comment.first_line, .Newline);
- var tok_i = comment.first_line + 1;
- while (true) : (tok_i += 1) {
- const tok_id = tree.token_ids[tok_i];
- if (tok_id == kind) {
- try renderToken(tree, ais, tok_i, .Newline);
- } else if (tok_id == .LineComment) {
- continue;
- } else {
- break;
- }
- }
- },
else => unreachable,
}
+ //switch (tag) {
+ // .FnProto => {
+ // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
+
+ // try renderDocComments(tree, ais, fn_proto, fn_proto.getDocComments());
+
+ // if (fn_proto.getBodyNode()) |body_node| {
+ // try renderExpression(allocator, ais, tree, decl, .Space);
+ // try renderExpression(allocator, ais, tree, body_node, space);
+ // } else {
+ // try renderExpression(allocator, ais, tree, decl, .None);
+ // try renderToken(ais, tree, tree.nextToken(decl.lastToken()), space);
+ // }
+ // },
+
+ // .Use => {
+ // const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
+
+ // if (use_decl.visib_token) |visib_token| {
+ // try renderToken(ais, tree, visib_token, .Space); // pub
+ // }
+ // try renderToken(ais, tree, use_decl.use_token, .Space); // usingnamespace
+ // try renderExpression(allocator, ais, tree, use_decl.expr, .None);
+ // try renderToken(ais, tree, use_decl.semicolon_token, space); // ;
+ // },
+
+ // .VarDecl => {
+ // const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
+
+ // try renderDocComments(tree, ais, var_decl, var_decl.getDocComments());
+ // try renderVarDecl(allocator, ais, tree, var_decl);
+ // },
+
+ // .TestDecl => {
+ // const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
+
+ // try renderDocComments(tree, ais, test_decl, test_decl.doc_comments);
+ // try renderToken(ais, tree, test_decl.test_token, .Space);
+ // if (test_decl.name) |name|
+ // try renderExpression(allocator, ais, tree, name, .Space);
+ // try renderExpression(allocator, ais, tree, test_decl.body_node, space);
+ // },
+
+ // .ContainerField => {
+ // const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
+
+ // try renderDocComments(tree, ais, field, field.doc_comments);
+ // if (field.comptime_token) |t| {
+ // try renderToken(ais, tree, t, .Space); // comptime
+ // }
+
+ // const src_has_trailing_comma = blk: {
+ // const maybe_comma = tree.nextToken(field.lastToken());
+ // break :blk tree.token_tags[maybe_comma] == .Comma;
+ // };
+
+ // // The trailing comma is emitted at the end, but if it's not present
+ // // we still have to respect the specified `space` parameter
+ // const last_token_space: Space = if (src_has_trailing_comma) .None else space;
+
+ // if (field.type_expr == null and field.value_expr == null) {
+ // try renderToken(ais, tree, field.name_token, last_token_space); // name
+ // } else if (field.type_expr != null and field.value_expr == null) {
+ // try renderToken(ais, tree, field.name_token, .None); // name
+ // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // :
+
+ // if (field.align_expr) |align_value_expr| {
+ // try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
+ // const lparen_token = tree.prevToken(align_value_expr.firstToken());
+ // const align_kw = tree.prevToken(lparen_token);
+ // const rparen_token = tree.nextToken(align_value_expr.lastToken());
+ // try renderToken(ais, tree, align_kw, .None); // align
+ // try renderToken(ais, tree, lparen_token, .None); // (
+ // try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
+ // try renderToken(ais, tree, rparen_token, last_token_space); // )
+ // } else {
+ // try renderExpression(allocator, ais, tree, field.type_expr.?, last_token_space); // type
+ // }
+ // } else if (field.type_expr == null and field.value_expr != null) {
+ // try renderToken(ais, tree, field.name_token, .Space); // name
+ // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // =
+ // try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
+ // } else {
+ // try renderToken(ais, tree, field.name_token, .None); // name
+ // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // :
+
+ // if (field.align_expr) |align_value_expr| {
+ // try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
+ // const lparen_token = tree.prevToken(align_value_expr.firstToken());
+ // const align_kw = tree.prevToken(lparen_token);
+ // const rparen_token = tree.nextToken(align_value_expr.lastToken());
+ // try renderToken(ais, tree, align_kw, .None); // align
+ // try renderToken(ais, tree, lparen_token, .None); // (
+ // try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
+ // try renderToken(ais, tree, rparen_token, .Space); // )
+ // } else {
+ // try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
+ // }
+ // try renderToken(ais, tree, tree.prevToken(field.value_expr.?.firstToken()), .Space); // =
+ // try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
+ // }
+
+ // if (src_has_trailing_comma) {
+ // const comma = tree.nextToken(field.lastToken());
+ // try renderToken(ais, tree, comma, space);
+ // }
+ // },
+
+ // .DocComment => {
+ // const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl);
+ // const kind = tree.token_tags[comment.first_line];
+ // try renderToken(ais, tree, comment.first_line, .Newline);
+ // var tok_i = comment.first_line + 1;
+ // while (true) : (tok_i += 1) {
+ // const tok_id = tree.token_tags[tok_i];
+ // if (tok_id == kind) {
+ // try renderToken(ais, tree, tok_i, .Newline);
+ // } else if (tok_id == .LineComment) {
+ // continue;
+ // } else {
+ // break;
+ // }
+ // }
+ // },
+ // else => unreachable,
+ //}
}
-fn renderExpression(
- allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
- base: *ast.Node,
- space: Space,
-) (@TypeOf(ais.*).Error || Error)!void {
- switch (base.tag) {
- .Identifier,
- .IntegerLiteral,
- .FloatLiteral,
- .StringLiteral,
- .CharLiteral,
- .BoolLiteral,
- .NullLiteral,
- .Unreachable,
- .ErrorType,
- .UndefinedLiteral,
- => {
- const casted_node = base.cast(ast.Node.OneToken).?;
- return renderToken(tree, ais, casted_node.token, space);
- },
-
- .AnyType => {
- const any_type = base.castTag(.AnyType).?;
- if (mem.eql(u8, tree.tokenSlice(any_type.token), "var")) {
- // TODO remove in next release cycle
- try ais.writer().writeAll("anytype");
- if (space == .Comma) try ais.writer().writeAll(",\n");
- return;
- }
- return renderToken(tree, ais, any_type.token, space);
- },
-
- .Block, .LabeledBlock => {
- const block: struct {
- label: ?ast.TokenIndex,
- statements: []*ast.Node,
- lbrace: ast.TokenIndex,
- rbrace: ast.TokenIndex,
- } = b: {
- if (base.castTag(.Block)) |block| {
- break :b .{
- .label = null,
- .statements = block.statements(),
- .lbrace = block.lbrace,
- .rbrace = block.rbrace,
- };
- } else if (base.castTag(.LabeledBlock)) |block| {
- break :b .{
- .label = block.label,
- .statements = block.statements(),
- .lbrace = block.lbrace,
- .rbrace = block.rbrace,
- };
- } else {
- unreachable;
- }
- };
-
- if (block.label) |label| {
- try renderToken(tree, ais, label, Space.None);
- try renderToken(tree, ais, tree.nextToken(label), Space.Space);
- }
-
- if (block.statements.len == 0) {
- ais.pushIndentNextLine();
- defer ais.popIndent();
- try renderToken(tree, ais, block.lbrace, Space.None);
- } else {
- ais.pushIndentNextLine();
- defer ais.popIndent();
-
- try renderToken(tree, ais, block.lbrace, Space.Newline);
-
- for (block.statements) |statement, i| {
- try renderStatement(allocator, ais, tree, statement);
-
- if (i + 1 < block.statements.len) {
- try renderExtraNewline(tree, ais, block.statements[i + 1]);
- }
- }
- }
- return renderToken(tree, ais, block.rbrace, space);
- },
-
- .Defer => {
- const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
-
- try renderToken(tree, ais, defer_node.defer_token, Space.Space);
- if (defer_node.payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Space);
- }
- return renderExpression(allocator, ais, tree, defer_node.expr, space);
- },
- .Comptime => {
- const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
-
- try renderToken(tree, ais, comptime_node.comptime_token, Space.Space);
- return renderExpression(allocator, ais, tree, comptime_node.expr, space);
- },
- .Nosuspend => {
- const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base);
- if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) {
- // TODO: remove this
- try ais.writer().writeAll("nosuspend ");
- } else {
- try renderToken(tree, ais, nosuspend_node.nosuspend_token, Space.Space);
- }
- return renderExpression(allocator, ais, tree, nosuspend_node.expr, space);
- },
-
- .Suspend => {
- const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
-
- if (suspend_node.body) |body| {
- try renderToken(tree, ais, suspend_node.suspend_token, Space.Space);
- return renderExpression(allocator, ais, tree, body, space);
- } else {
- return renderToken(tree, ais, suspend_node.suspend_token, space);
- }
- },
-
- .Catch => {
- const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base);
-
- const op_space = Space.Space;
- try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
-
- const after_op_space = blk: {
- const same_line = tree.tokensOnSameLine(infix_op_node.op_token, tree.nextToken(infix_op_node.op_token));
- break :blk if (same_line) op_space else Space.Newline;
- };
-
- try renderToken(tree, ais, infix_op_node.op_token, after_op_space);
-
- if (infix_op_node.payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Space);
- }
-
- ais.pushIndentOneShot();
- return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
- },
-
- .Add,
- .AddWrap,
- .ArrayCat,
- .ArrayMult,
- .Assign,
- .AssignBitAnd,
- .AssignBitOr,
- .AssignBitShiftLeft,
- .AssignBitShiftRight,
- .AssignBitXor,
- .AssignDiv,
- .AssignSub,
- .AssignSubWrap,
- .AssignMod,
- .AssignAdd,
- .AssignAddWrap,
- .AssignMul,
- .AssignMulWrap,
- .BangEqual,
- .BitAnd,
- .BitOr,
- .BitShiftLeft,
- .BitShiftRight,
- .BitXor,
- .BoolAnd,
- .BoolOr,
- .Div,
- .EqualEqual,
- .ErrorUnion,
- .GreaterOrEqual,
- .GreaterThan,
- .LessOrEqual,
- .LessThan,
- .MergeErrorSets,
- .Mod,
- .Mul,
- .MulWrap,
- .Period,
- .Range,
- .Sub,
- .SubWrap,
- .OrElse,
- => {
- const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base);
-
- const op_space = switch (base.tag) {
- .Period, .ErrorUnion, .Range => Space.None,
- else => Space.Space,
- };
- try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
-
- const after_op_space = blk: {
- const loc = tree.tokenLocation(tree.token_locs[infix_op_node.op_token].end, tree.nextToken(infix_op_node.op_token));
- break :blk if (loc.line == 0) op_space else Space.Newline;
- };
-
- {
- ais.pushIndent();
- defer ais.popIndent();
- try renderToken(tree, ais, infix_op_node.op_token, after_op_space);
- }
- ais.pushIndentOneShot();
- return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
- },
-
- .BitNot,
- .BoolNot,
- .Negation,
- .NegationWrap,
- .OptionalType,
- .AddressOf,
- => {
- const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
- try renderToken(tree, ais, casted_node.op_token, Space.None);
- return renderExpression(allocator, ais, tree, casted_node.rhs, space);
- },
-
- .Try,
- .Resume,
- .Await,
- => {
- const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
- try renderToken(tree, ais, casted_node.op_token, Space.Space);
- return renderExpression(allocator, ais, tree, casted_node.rhs, space);
- },
-
- .ArrayType => {
- const array_type = @fieldParentPtr(ast.Node.ArrayType, "base", base);
- return renderArrayType(
- allocator,
- ais,
- tree,
- array_type.op_token,
- array_type.rhs,
- array_type.len_expr,
- null,
- space,
- );
- },
- .ArrayTypeSentinel => {
- const array_type = @fieldParentPtr(ast.Node.ArrayTypeSentinel, "base", base);
- return renderArrayType(
- allocator,
- ais,
- tree,
- array_type.op_token,
- array_type.rhs,
- array_type.len_expr,
- array_type.sentinel,
- space,
- );
- },
-
- .PtrType => {
- const ptr_type = @fieldParentPtr(ast.Node.PtrType, "base", base);
- const op_tok_id = tree.token_ids[ptr_type.op_token];
- switch (op_tok_id) {
- .Asterisk, .AsteriskAsterisk => try ais.writer().writeByte('*'),
- .LBracket => if (tree.token_ids[ptr_type.op_token + 2] == .Identifier)
- try ais.writer().writeAll("[*c")
- else
- try ais.writer().writeAll("[*"),
- else => unreachable,
- }
- if (ptr_type.ptr_info.sentinel) |sentinel| {
- const colon_token = tree.prevToken(sentinel.firstToken());
- try renderToken(tree, ais, colon_token, Space.None); // :
- const sentinel_space = switch (op_tok_id) {
- .LBracket => Space.None,
- else => Space.Space,
- };
- try renderExpression(allocator, ais, tree, sentinel, sentinel_space);
- }
- switch (op_tok_id) {
- .Asterisk, .AsteriskAsterisk => {},
- .LBracket => try ais.writer().writeByte(']'),
- else => unreachable,
- }
- if (ptr_type.ptr_info.allowzero_token) |allowzero_token| {
- try renderToken(tree, ais, allowzero_token, Space.Space); // allowzero
- }
- if (ptr_type.ptr_info.align_info) |align_info| {
- const lparen_token = tree.prevToken(align_info.node.firstToken());
- const align_token = tree.prevToken(lparen_token);
-
- try renderToken(tree, ais, align_token, Space.None); // align
- try renderToken(tree, ais, lparen_token, Space.None); // (
-
- try renderExpression(allocator, ais, tree, align_info.node, Space.None);
-
- if (align_info.bit_range) |bit_range| {
- const colon1 = tree.prevToken(bit_range.start.firstToken());
- const colon2 = tree.prevToken(bit_range.end.firstToken());
-
- try renderToken(tree, ais, colon1, Space.None); // :
- try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
- try renderToken(tree, ais, colon2, Space.None); // :
- try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
-
- const rparen_token = tree.nextToken(bit_range.end.lastToken());
- try renderToken(tree, ais, rparen_token, Space.Space); // )
- } else {
- const rparen_token = tree.nextToken(align_info.node.lastToken());
- try renderToken(tree, ais, rparen_token, Space.Space); // )
- }
- }
- if (ptr_type.ptr_info.const_token) |const_token| {
- try renderToken(tree, ais, const_token, Space.Space); // const
- }
- if (ptr_type.ptr_info.volatile_token) |volatile_token| {
- try renderToken(tree, ais, volatile_token, Space.Space); // volatile
- }
- return renderExpression(allocator, ais, tree, ptr_type.rhs, space);
- },
-
- .SliceType => {
- const slice_type = @fieldParentPtr(ast.Node.SliceType, "base", base);
- try renderToken(tree, ais, slice_type.op_token, Space.None); // [
- if (slice_type.ptr_info.sentinel) |sentinel| {
- const colon_token = tree.prevToken(sentinel.firstToken());
- try renderToken(tree, ais, colon_token, Space.None); // :
- try renderExpression(allocator, ais, tree, sentinel, Space.None);
- try renderToken(tree, ais, tree.nextToken(sentinel.lastToken()), Space.None); // ]
- } else {
- try renderToken(tree, ais, tree.nextToken(slice_type.op_token), Space.None); // ]
- }
-
- if (slice_type.ptr_info.allowzero_token) |allowzero_token| {
- try renderToken(tree, ais, allowzero_token, Space.Space); // allowzero
- }
- if (slice_type.ptr_info.align_info) |align_info| {
- const lparen_token = tree.prevToken(align_info.node.firstToken());
- const align_token = tree.prevToken(lparen_token);
-
- try renderToken(tree, ais, align_token, Space.None); // align
- try renderToken(tree, ais, lparen_token, Space.None); // (
-
- try renderExpression(allocator, ais, tree, align_info.node, Space.None);
-
- if (align_info.bit_range) |bit_range| {
- const colon1 = tree.prevToken(bit_range.start.firstToken());
- const colon2 = tree.prevToken(bit_range.end.firstToken());
-
- try renderToken(tree, ais, colon1, Space.None); // :
- try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
- try renderToken(tree, ais, colon2, Space.None); // :
- try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
-
- const rparen_token = tree.nextToken(bit_range.end.lastToken());
- try renderToken(tree, ais, rparen_token, Space.Space); // )
- } else {
- const rparen_token = tree.nextToken(align_info.node.lastToken());
- try renderToken(tree, ais, rparen_token, Space.Space); // )
- }
- }
- if (slice_type.ptr_info.const_token) |const_token| {
- try renderToken(tree, ais, const_token, Space.Space);
- }
- if (slice_type.ptr_info.volatile_token) |volatile_token| {
- try renderToken(tree, ais, volatile_token, Space.Space);
- }
- return renderExpression(allocator, ais, tree, slice_type.rhs, space);
- },
-
- .ArrayInitializer, .ArrayInitializerDot => {
- var rtoken: ast.TokenIndex = undefined;
- var exprs: []*ast.Node = undefined;
- const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) {
- .ArrayInitializerDot => blk: {
- const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base);
- rtoken = casted.rtoken;
- exprs = casted.list();
- break :blk .{ .dot = casted.dot };
- },
- .ArrayInitializer => blk: {
- const casted = @fieldParentPtr(ast.Node.ArrayInitializer, "base", base);
- rtoken = casted.rtoken;
- exprs = casted.list();
- break :blk .{ .node = casted.lhs };
- },
- else => unreachable,
- };
-
- const lbrace = switch (lhs) {
- .dot => |dot| tree.nextToken(dot),
- .node => |node| tree.nextToken(node.lastToken()),
- };
-
- switch (lhs) {
- .dot => |dot| try renderToken(tree, ais, dot, Space.None),
- .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
- }
-
- if (exprs.len == 0) {
- try renderToken(tree, ais, lbrace, Space.None);
- return renderToken(tree, ais, rtoken, space);
- }
-
- if (exprs.len == 1 and exprs[0].tag != .MultilineStringLiteral and tree.token_ids[exprs[0].*.lastToken() + 1] == .RBrace) {
- const expr = exprs[0];
-
- try renderToken(tree, ais, lbrace, Space.None);
- try renderExpression(allocator, ais, tree, expr, Space.None);
- return renderToken(tree, ais, rtoken, space);
- }
-
- // scan to find row size
- if (rowSize(tree, exprs, rtoken) != null) {
- {
- ais.pushIndentNextLine();
- defer ais.popIndent();
- try renderToken(tree, ais, lbrace, Space.Newline);
-
- var expr_index: usize = 0;
- while (rowSize(tree, exprs[expr_index..], rtoken)) |row_size| {
- const row_exprs = exprs[expr_index..];
- // A place to store the width of each expression and its column's maximum
- var widths = try allocator.alloc(usize, row_exprs.len + row_size);
- defer allocator.free(widths);
- mem.set(usize, widths, 0);
-
- var expr_newlines = try allocator.alloc(bool, row_exprs.len);
- defer allocator.free(expr_newlines);
- mem.set(bool, expr_newlines, false);
-
- var expr_widths = widths[0 .. widths.len - row_size];
- var column_widths = widths[widths.len - row_size ..];
-
- // Find next row with trailing comment (if any) to end the current section
- var section_end = sec_end: {
- var this_line_first_expr: usize = 0;
- var this_line_size = rowSize(tree, row_exprs, rtoken);
- for (row_exprs) |expr, i| {
- // Ignore comment on first line of this section
- if (i == 0 or tree.tokensOnSameLine(row_exprs[0].firstToken(), expr.lastToken())) continue;
- // Track start of line containing comment
- if (!tree.tokensOnSameLine(row_exprs[this_line_first_expr].firstToken(), expr.lastToken())) {
- this_line_first_expr = i;
- this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rtoken);
- }
-
- const maybe_comma = expr.lastToken() + 1;
- const maybe_comment = expr.lastToken() + 2;
- if (maybe_comment < tree.token_ids.len) {
- if (tree.token_ids[maybe_comma] == .Comma and
- tree.token_ids[maybe_comment] == .LineComment and
- tree.tokensOnSameLine(expr.lastToken(), maybe_comment))
- {
- var comment_token_loc = tree.token_locs[maybe_comment];
- const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2;
- if (!comment_is_empty) {
- // Found row ending in comment
- break :sec_end i - this_line_size.? + 1;
- }
- }
- }
- }
- break :sec_end row_exprs.len;
- };
- expr_index += section_end;
-
- const section_exprs = row_exprs[0..section_end];
-
- // Null stream for counting the printed length of each expression
- var line_find_stream = std.io.findByteWriter('\n', std.io.null_writer);
- var counting_stream = std.io.countingWriter(line_find_stream.writer());
- var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer());
-
- // Calculate size of columns in current section
- var column_counter: usize = 0;
- var single_line = true;
- for (section_exprs) |expr, i| {
- if (i + 1 < section_exprs.len) {
- counting_stream.bytes_written = 0;
- line_find_stream.byte_found = false;
- try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
- const width = @intCast(usize, counting_stream.bytes_written);
- expr_widths[i] = width;
- expr_newlines[i] = line_find_stream.byte_found;
-
- if (!line_find_stream.byte_found) {
- const column = column_counter % row_size;
- column_widths[column] = std.math.max(column_widths[column], width);
-
- const expr_last_token = expr.*.lastToken() + 1;
- const next_expr = section_exprs[i + 1];
- const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, next_expr.*.firstToken());
-
- column_counter += 1;
-
- if (loc.line != 0) single_line = false;
- } else {
- single_line = false;
- column_counter = 0;
- }
- } else {
- counting_stream.bytes_written = 0;
- try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
- const width = @intCast(usize, counting_stream.bytes_written);
- expr_widths[i] = width;
- expr_newlines[i] = line_find_stream.byte_found;
-
- if (!line_find_stream.byte_found) {
- const column = column_counter % row_size;
- column_widths[column] = std.math.max(column_widths[column], width);
- }
- break;
- }
- }
-
- // Render exprs in current section
- column_counter = 0;
- var last_col_index: usize = row_size - 1;
- for (section_exprs) |expr, i| {
- if (i + 1 < section_exprs.len) {
- const next_expr = section_exprs[i + 1];
- try renderExpression(allocator, ais, tree, expr, Space.None);
-
- const comma = tree.nextToken(expr.*.lastToken());
-
- if (column_counter != last_col_index) {
- if (!expr_newlines[i] and !expr_newlines[i + 1]) {
- // Neither the current or next expression is multiline
- try renderToken(tree, ais, comma, Space.Space); // ,
- assert(column_widths[column_counter % row_size] >= expr_widths[i]);
- const padding = column_widths[column_counter % row_size] - expr_widths[i];
- try ais.writer().writeByteNTimes(' ', padding);
-
- column_counter += 1;
- continue;
- }
- }
- if (single_line and row_size != 1) {
- try renderToken(tree, ais, comma, Space.Space); // ,
- continue;
- }
-
- column_counter = 0;
- try renderToken(tree, ais, comma, Space.Newline); // ,
- try renderExtraNewline(tree, ais, next_expr);
- } else {
- const maybe_comma = tree.nextToken(expr.*.lastToken());
- if (tree.token_ids[maybe_comma] == .Comma) {
- try renderExpression(allocator, ais, tree, expr, Space.None); // ,
- try renderToken(tree, ais, maybe_comma, Space.Newline); // ,
- } else {
- try renderExpression(allocator, ais, tree, expr, Space.Comma); // ,
- }
- }
- }
-
- if (expr_index == exprs.len) {
- break;
- }
- }
- }
-
- return renderToken(tree, ais, rtoken, space);
- }
-
- // Single line
- try renderToken(tree, ais, lbrace, Space.Space);
- for (exprs) |expr, i| {
- if (i + 1 < exprs.len) {
- const next_expr = exprs[i + 1];
- try renderExpression(allocator, ais, tree, expr, Space.None);
- const comma = tree.nextToken(expr.*.lastToken());
- try renderToken(tree, ais, comma, Space.Space); // ,
- } else {
- try renderExpression(allocator, ais, tree, expr, Space.Space);
- }
- }
-
- return renderToken(tree, ais, rtoken, space);
- },
-
- .StructInitializer, .StructInitializerDot => {
- var rtoken: ast.TokenIndex = undefined;
- var field_inits: []*ast.Node = undefined;
- const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) {
- .StructInitializerDot => blk: {
- const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base);
- rtoken = casted.rtoken;
- field_inits = casted.list();
- break :blk .{ .dot = casted.dot };
- },
- .StructInitializer => blk: {
- const casted = @fieldParentPtr(ast.Node.StructInitializer, "base", base);
- rtoken = casted.rtoken;
- field_inits = casted.list();
- break :blk .{ .node = casted.lhs };
- },
- else => unreachable,
- };
-
- const lbrace = switch (lhs) {
- .dot => |dot| tree.nextToken(dot),
- .node => |node| tree.nextToken(node.lastToken()),
- };
-
- if (field_inits.len == 0) {
- switch (lhs) {
- .dot => |dot| try renderToken(tree, ais, dot, Space.None),
- .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
- }
-
- {
- ais.pushIndentNextLine();
- defer ais.popIndent();
- try renderToken(tree, ais, lbrace, Space.None);
- }
-
- return renderToken(tree, ais, rtoken, space);
- }
-
- const src_has_trailing_comma = blk: {
- const maybe_comma = tree.prevToken(rtoken);
- break :blk tree.token_ids[maybe_comma] == .Comma;
- };
-
- const src_same_line = blk: {
- const loc = tree.tokenLocation(tree.token_locs[lbrace].end, rtoken);
- break :blk loc.line == 0;
- };
-
- const expr_outputs_one_line = blk: {
- // render field expressions until a LF is found
- for (field_inits) |field_init| {
- var find_stream = std.io.findByteWriter('\n', std.io.null_writer);
- var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, find_stream.writer());
-
- try renderExpression(allocator, &auto_indenting_stream, tree, field_init, Space.None);
- if (find_stream.byte_found) break :blk false;
- }
- break :blk true;
- };
-
- if (field_inits.len == 1) blk: {
- if (field_inits[0].cast(ast.Node.FieldInitializer)) |field_init| {
- switch (field_init.expr.tag) {
- .StructInitializer,
- .StructInitializerDot,
- => break :blk,
- else => {},
- }
- }
-
- // if the expression outputs to multiline, make this struct multiline
- if (!expr_outputs_one_line or src_has_trailing_comma) {
- break :blk;
- }
-
- switch (lhs) {
- .dot => |dot| try renderToken(tree, ais, dot, Space.None),
- .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
- }
- try renderToken(tree, ais, lbrace, Space.Space);
- try renderExpression(allocator, ais, tree, field_inits[0], Space.Space);
- return renderToken(tree, ais, rtoken, space);
- }
-
- if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
- // render all on one line, no trailing comma
- switch (lhs) {
- .dot => |dot| try renderToken(tree, ais, dot, Space.None),
- .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
- }
- try renderToken(tree, ais, lbrace, Space.Space);
-
- for (field_inits) |field_init, i| {
- if (i + 1 < field_inits.len) {
- try renderExpression(allocator, ais, tree, field_init, Space.None);
-
- const comma = tree.nextToken(field_init.lastToken());
- try renderToken(tree, ais, comma, Space.Space);
- } else {
- try renderExpression(allocator, ais, tree, field_init, Space.Space);
- }
- }
-
- return renderToken(tree, ais, rtoken, space);
- }
-
- {
- switch (lhs) {
- .dot => |dot| try renderToken(tree, ais, dot, Space.None),
- .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
- }
-
- ais.pushIndentNextLine();
- defer ais.popIndent();
-
- try renderToken(tree, ais, lbrace, Space.Newline);
-
- for (field_inits) |field_init, i| {
- if (i + 1 < field_inits.len) {
- const next_field_init = field_inits[i + 1];
- try renderExpression(allocator, ais, tree, field_init, Space.None);
-
- const comma = tree.nextToken(field_init.lastToken());
- try renderToken(tree, ais, comma, Space.Newline);
-
- try renderExtraNewline(tree, ais, next_field_init);
- } else {
- try renderExpression(allocator, ais, tree, field_init, Space.Comma);
- }
- }
- }
-
- return renderToken(tree, ais, rtoken, space);
- },
-
- .Call => {
- const call = @fieldParentPtr(ast.Node.Call, "base", base);
- if (call.async_token) |async_token| {
- try renderToken(tree, ais, async_token, Space.Space);
- }
-
- try renderExpression(allocator, ais, tree, call.lhs, Space.None);
-
- const lparen = tree.nextToken(call.lhs.lastToken());
-
- if (call.params_len == 0) {
- try renderToken(tree, ais, lparen, Space.None);
- return renderToken(tree, ais, call.rtoken, space);
- }
-
- const src_has_trailing_comma = blk: {
- const maybe_comma = tree.prevToken(call.rtoken);
- break :blk tree.token_ids[maybe_comma] == .Comma;
- };
-
- if (src_has_trailing_comma) {
- {
- ais.pushIndent();
- defer ais.popIndent();
-
- try renderToken(tree, ais, lparen, Space.Newline); // (
- const params = call.params();
- for (params) |param_node, i| {
- if (i + 1 < params.len) {
- const next_node = params[i + 1];
- try renderExpression(allocator, ais, tree, param_node, Space.None);
-
- // Unindent the comma for multiline string literals
- const maybe_multiline_string = param_node.firstToken();
- const is_multiline_string = tree.token_ids[maybe_multiline_string] == .MultilineStringLiteralLine;
- if (is_multiline_string) ais.popIndent();
- defer if (is_multiline_string) ais.pushIndent();
-
- const comma = tree.nextToken(param_node.lastToken());
- try renderToken(tree, ais, comma, Space.Newline); // ,
- try renderExtraNewline(tree, ais, next_node);
- } else {
- try renderExpression(allocator, ais, tree, param_node, Space.Comma);
- }
- }
- }
- return renderToken(tree, ais, call.rtoken, space);
- }
-
- try renderToken(tree, ais, lparen, Space.None); // (
-
- const params = call.params();
- for (params) |param_node, i| {
- const maybe_comment = param_node.firstToken() - 1;
- const maybe_multiline_string = param_node.firstToken();
- if (tree.token_ids[maybe_multiline_string] == .MultilineStringLiteralLine or tree.token_ids[maybe_comment] == .LineComment) {
- ais.pushIndentOneShot();
- }
-
- try renderExpression(allocator, ais, tree, param_node, Space.None);
-
- if (i + 1 < params.len) {
- const comma = tree.nextToken(param_node.lastToken());
- try renderToken(tree, ais, comma, Space.Space);
- }
- }
- return renderToken(tree, ais, call.rtoken, space); // )
- },
-
- .ArrayAccess => {
- const suffix_op = base.castTag(.ArrayAccess).?;
-
- const lbracket = tree.nextToken(suffix_op.lhs.lastToken());
- const rbracket = tree.nextToken(suffix_op.index_expr.lastToken());
-
- try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
- try renderToken(tree, ais, lbracket, Space.None); // [
-
- const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment;
- const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment;
- {
- const new_space = if (ends_with_comment) Space.Newline else Space.None;
-
- ais.pushIndent();
- defer ais.popIndent();
- try renderExpression(allocator, ais, tree, suffix_op.index_expr, new_space);
- }
- if (starts_with_comment) try ais.maybeInsertNewline();
- return renderToken(tree, ais, rbracket, space); // ]
- },
-
- .Slice => {
- const suffix_op = base.castTag(.Slice).?;
- try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
-
- const lbracket = tree.prevToken(suffix_op.start.firstToken());
- const dotdot = tree.nextToken(suffix_op.start.lastToken());
-
- const after_start_space_bool = nodeCausesSliceOpSpace(suffix_op.start) or
- (if (suffix_op.end) |end| nodeCausesSliceOpSpace(end) else false);
- const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
- const after_op_space = if (suffix_op.end != null) after_start_space else Space.None;
-
- try renderToken(tree, ais, lbracket, Space.None); // [
- try renderExpression(allocator, ais, tree, suffix_op.start, after_start_space);
- try renderToken(tree, ais, dotdot, after_op_space); // ..
- if (suffix_op.end) |end| {
- const after_end_space = if (suffix_op.sentinel != null) Space.Space else Space.None;
- try renderExpression(allocator, ais, tree, end, after_end_space);
- }
- if (suffix_op.sentinel) |sentinel| {
- const colon = tree.prevToken(sentinel.firstToken());
- try renderToken(tree, ais, colon, Space.None); // :
- try renderExpression(allocator, ais, tree, sentinel, Space.None);
- }
- return renderToken(tree, ais, suffix_op.rtoken, space); // ]
- },
-
- .Deref => {
- const suffix_op = base.castTag(.Deref).?;
-
- try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
- return renderToken(tree, ais, suffix_op.rtoken, space); // .*
- },
- .UnwrapOptional => {
- const suffix_op = base.castTag(.UnwrapOptional).?;
-
- try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
- try renderToken(tree, ais, tree.prevToken(suffix_op.rtoken), Space.None); // .
- return renderToken(tree, ais, suffix_op.rtoken, space); // ?
- },
-
- .Break => {
- const flow_expr = base.castTag(.Break).?;
- const maybe_rhs = flow_expr.getRHS();
- const maybe_label = flow_expr.getLabel();
-
- if (maybe_label == null and maybe_rhs == null) {
- return renderToken(tree, ais, flow_expr.ltoken, space); // break
- }
-
- try renderToken(tree, ais, flow_expr.ltoken, Space.Space); // break
- if (maybe_label) |label| {
- const colon = tree.nextToken(flow_expr.ltoken);
- try renderToken(tree, ais, colon, Space.None); // :
-
- if (maybe_rhs == null) {
- return renderToken(tree, ais, label, space); // label
- }
- try renderToken(tree, ais, label, Space.Space); // label
- }
- return renderExpression(allocator, ais, tree, maybe_rhs.?, space);
- },
-
- .Continue => {
- const flow_expr = base.castTag(.Continue).?;
- if (flow_expr.getLabel()) |label| {
- try renderToken(tree, ais, flow_expr.ltoken, Space.Space); // continue
- const colon = tree.nextToken(flow_expr.ltoken);
- try renderToken(tree, ais, colon, Space.None); // :
- return renderToken(tree, ais, label, space); // label
- } else {
- return renderToken(tree, ais, flow_expr.ltoken, space); // continue
- }
- },
-
- .Return => {
- const flow_expr = base.castTag(.Return).?;
- if (flow_expr.getRHS()) |rhs| {
- try renderToken(tree, ais, flow_expr.ltoken, Space.Space);
- return renderExpression(allocator, ais, tree, rhs, space);
- } else {
- return renderToken(tree, ais, flow_expr.ltoken, space);
- }
- },
-
- .Payload => {
- const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
-
- try renderToken(tree, ais, payload.lpipe, Space.None);
- try renderExpression(allocator, ais, tree, payload.error_symbol, Space.None);
- return renderToken(tree, ais, payload.rpipe, space);
- },
-
- .PointerPayload => {
- const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
-
- try renderToken(tree, ais, payload.lpipe, Space.None);
- if (payload.ptr_token) |ptr_token| {
- try renderToken(tree, ais, ptr_token, Space.None);
- }
- try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
- return renderToken(tree, ais, payload.rpipe, space);
- },
-
- .PointerIndexPayload => {
- const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
-
- try renderToken(tree, ais, payload.lpipe, Space.None);
- if (payload.ptr_token) |ptr_token| {
- try renderToken(tree, ais, ptr_token, Space.None);
- }
- try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
-
- if (payload.index_symbol) |index_symbol| {
- const comma = tree.nextToken(payload.value_symbol.lastToken());
-
- try renderToken(tree, ais, comma, Space.Space);
- try renderExpression(allocator, ais, tree, index_symbol, Space.None);
- }
-
- return renderToken(tree, ais, payload.rpipe, space);
- },
-
- .GroupedExpression => {
- const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
-
- try renderToken(tree, ais, grouped_expr.lparen, Space.None);
+fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {
+ const token_tags = tree.tokens.items(.tag);
+ const main_tokens = tree.nodes.items(.main_token);
+ switch (tree.nodes.items(.tag)[node]) {
+ //.Identifier,
+ //.IntegerLiteral,
+ //.FloatLiteral,
+ //.StringLiteral,
+ //.CharLiteral,
+ //.BoolLiteral,
+ //.NullLiteral,
+ //.Unreachable,
+ //.ErrorType,
+ //.UndefinedLiteral,
+ //=> {
+ // const casted_node = base.cast(ast.Node.OneToken).?;
+ // return renderToken(ais, tree, casted_node.token, space);
+ //},
+
+ //.AnyType => {
+ // const any_type = base.castTag(.AnyType).?;
+ // if (mem.eql(u8, tree.tokenSlice(any_type.token), "var")) {
+ // // TODO remove in next release cycle
+ // try ais.writer().writeAll("anytype");
+ // if (space == .Comma) try ais.writer().writeAll(",\n");
+ // return;
+ // }
+ // return renderToken(ais, tree, any_type.token, space);
+ //},
+ .Block => {
+ const lbrace = main_tokens[node];
+ if (token_tags[lbrace - 1] == .Colon and
+ token_tags[lbrace - 2] == .Identifier)
{
- ais.pushIndentOneShot();
- try renderExpression(allocator, ais, tree, grouped_expr.expr, Space.None);
- }
- return renderToken(tree, ais, grouped_expr.rparen, space);
- },
-
- .FieldInitializer => {
- const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
-
- try renderToken(tree, ais, field_init.period_token, Space.None); // .
- try renderToken(tree, ais, field_init.name_token, Space.Space); // name
- try renderToken(tree, ais, tree.nextToken(field_init.name_token), Space.Space); // =
- return renderExpression(allocator, ais, tree, field_init.expr, space);
- },
-
- .ContainerDecl => {
- const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
-
- if (container_decl.layout_token) |layout_token| {
- try renderToken(tree, ais, layout_token, Space.Space);
- }
-
- switch (container_decl.init_arg_expr) {
- .None => {
- try renderToken(tree, ais, container_decl.kind_token, Space.Space); // union
- },
- .Enum => |enum_tag_type| {
- try renderToken(tree, ais, container_decl.kind_token, Space.None); // union
-
- const lparen = tree.nextToken(container_decl.kind_token);
- const enum_token = tree.nextToken(lparen);
-
- try renderToken(tree, ais, lparen, Space.None); // (
- try renderToken(tree, ais, enum_token, Space.None); // enum
-
- if (enum_tag_type) |expr| {
- try renderToken(tree, ais, tree.nextToken(enum_token), Space.None); // (
- try renderExpression(allocator, ais, tree, expr, Space.None);
-
- const rparen = tree.nextToken(expr.lastToken());
- try renderToken(tree, ais, rparen, Space.None); // )
- try renderToken(tree, ais, tree.nextToken(rparen), Space.Space); // )
- } else {
- try renderToken(tree, ais, tree.nextToken(enum_token), Space.Space); // )
- }
- },
- .Type => |type_expr| {
- try renderToken(tree, ais, container_decl.kind_token, Space.None); // union
-
- const lparen = tree.nextToken(container_decl.kind_token);
- const rparen = tree.nextToken(type_expr.lastToken());
-
- try renderToken(tree, ais, lparen, Space.None); // (
- try renderExpression(allocator, ais, tree, type_expr, Space.None);
- try renderToken(tree, ais, rparen, Space.Space); // )
- },
+ try renderToken(ais, tree, lbrace - 2, .None);
+ try renderToken(ais, tree, lbrace - 1, .Space);
}
+ const nodes_data = tree.nodes.items(.data);
+ const statements = tree.extra_data[nodes_data[node].lhs..nodes_data[node].rhs];
- if (container_decl.fields_and_decls_len == 0) {
- {
- ais.pushIndentNextLine();
- defer ais.popIndent();
- try renderToken(tree, ais, container_decl.lbrace_token, Space.None); // {
- }
- return renderToken(tree, ais, container_decl.rbrace_token, space); // }
- }
-
- const src_has_trailing_comma = blk: {
- var maybe_comma = tree.prevToken(container_decl.lastToken());
- // Doc comments for a field may also appear after the comma, eg.
- // field_name: T, // comment attached to field_name
- if (tree.token_ids[maybe_comma] == .DocComment)
- maybe_comma = tree.prevToken(maybe_comma);
- break :blk tree.token_ids[maybe_comma] == .Comma;
- };
-
- const fields_and_decls = container_decl.fieldsAndDecls();
-
- // Check if the first declaration and the { are on the same line
- const src_has_newline = !tree.tokensOnSameLine(
- container_decl.lbrace_token,
- fields_and_decls[0].firstToken(),
- );
-
- // We can only print all the elements in-line if all the
- // declarations inside are fields
- const src_has_only_fields = blk: {
- for (fields_and_decls) |decl| {
- if (decl.tag != .ContainerField) break :blk false;
- }
- break :blk true;
- };
-
- if (src_has_trailing_comma or !src_has_only_fields) {
- // One declaration per line
+ if (statements.len == 0) {
ais.pushIndentNextLine();
- defer ais.popIndent();
- try renderToken(tree, ais, container_decl.lbrace_token, .Newline); // {
-
- for (fields_and_decls) |decl, i| {
- try renderContainerDecl(allocator, ais, tree, decl, .Newline);
-
- if (i + 1 < fields_and_decls.len) {
- try renderExtraNewline(tree, ais, fields_and_decls[i + 1]);
- }
- }
- } else if (src_has_newline) {
- // All the declarations on the same line, but place the items on
- // their own line
- try renderToken(tree, ais, container_decl.lbrace_token, .Newline); // {
-
- ais.pushIndent();
- defer ais.popIndent();
-
- for (fields_and_decls) |decl, i| {
- const space_after_decl: Space = if (i + 1 >= fields_and_decls.len) .Newline else .Space;
- try renderContainerDecl(allocator, ais, tree, decl, space_after_decl);
- }
- } else {
- // All the declarations on the same line
- try renderToken(tree, ais, container_decl.lbrace_token, .Space); // {
-
- for (fields_and_decls) |decl| {
- try renderContainerDecl(allocator, ais, tree, decl, .Space);
- }
- }
-
- return renderToken(tree, ais, container_decl.rbrace_token, space); // }
- },
-
- .ErrorSetDecl => {
- const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
-
- const lbrace = tree.nextToken(err_set_decl.error_token);
-
- if (err_set_decl.decls_len == 0) {
- try renderToken(tree, ais, err_set_decl.error_token, Space.None);
- try renderToken(tree, ais, lbrace, Space.None);
- return renderToken(tree, ais, err_set_decl.rbrace_token, space);
- }
-
- if (err_set_decl.decls_len == 1) blk: {
- const node = err_set_decl.decls()[0];
-
- // if there are any doc comments or same line comments
- // don't try to put it all on one line
- if (node.cast(ast.Node.ErrorTag)) |tag| {
- if (tag.doc_comments != null) break :blk;
- } else {
- break :blk;
- }
-
- try renderToken(tree, ais, err_set_decl.error_token, Space.None); // error
- try renderToken(tree, ais, lbrace, Space.None); // {
- try renderExpression(allocator, ais, tree, node, Space.None);
- return renderToken(tree, ais, err_set_decl.rbrace_token, space); // }
- }
-
- try renderToken(tree, ais, err_set_decl.error_token, Space.None); // error
-
- const src_has_trailing_comma = blk: {
- const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
- break :blk tree.token_ids[maybe_comma] == .Comma;
- };
-
- if (src_has_trailing_comma) {
- {
- ais.pushIndent();
- defer ais.popIndent();
-
- try renderToken(tree, ais, lbrace, Space.Newline); // {
- const decls = err_set_decl.decls();
- for (decls) |node, i| {
- if (i + 1 < decls.len) {
- try renderExpression(allocator, ais, tree, node, Space.None);
- try renderToken(tree, ais, tree.nextToken(node.lastToken()), Space.Newline); // ,
-
- try renderExtraNewline(tree, ais, decls[i + 1]);
- } else {
- try renderExpression(allocator, ais, tree, node, Space.Comma);
- }
- }
- }
-
- return renderToken(tree, ais, err_set_decl.rbrace_token, space); // }
+ try renderToken(ais, tree, lbrace, .None);
+ ais.popIndent();
+ const rbrace = lbrace + 1;
+ return renderToken(ais, tree, rbrace, space);
} else {
- try renderToken(tree, ais, lbrace, Space.Space); // {
-
- const decls = err_set_decl.decls();
- for (decls) |node, i| {
- if (i + 1 < decls.len) {
- try renderExpression(allocator, ais, tree, node, Space.None);
-
- const comma_token = tree.nextToken(node.lastToken());
- assert(tree.token_ids[comma_token] == .Comma);
- try renderToken(tree, ais, comma_token, Space.Space); // ,
- try renderExtraNewline(tree, ais, decls[i + 1]);
- } else {
- try renderExpression(allocator, ais, tree, node, Space.Space);
- }
- }
-
- return renderToken(tree, ais, err_set_decl.rbrace_token, space); // }
- }
- },
-
- .ErrorTag => {
- const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
-
- try renderDocComments(tree, ais, tag, tag.doc_comments);
- return renderToken(tree, ais, tag.name_token, space); // name
- },
-
- .MultilineStringLiteral => {
- const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
-
- {
- const locked_indents = ais.lockOneShotIndent();
- defer {
- var i: u8 = 0;
- while (i < locked_indents) : (i += 1) ais.popIndent();
- }
- try ais.maybeInsertNewline();
-
- for (multiline_str_literal.lines()) |t| try renderToken(tree, ais, t, Space.None);
- }
- },
-
- .BuiltinCall => {
- const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
-
- // TODO remove after 0.7.0 release
- if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
- return ais.writer().writeAll("opaque {}");
-
- // TODO remove after 0.7.0 release
- {
- const params = builtin_call.paramsConst();
- if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
- params.len == 1)
- {
- if (params[0].castTag(.EnumLiteral)) |enum_literal|
- if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
- return ais.writer().writeAll("opaque {}");
- }
- }
-
- try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name
-
- const src_params_trailing_comma = blk: {
- if (builtin_call.params_len == 0) break :blk false;
- const last_node = builtin_call.params()[builtin_call.params_len - 1];
- const maybe_comma = tree.nextToken(last_node.lastToken());
- break :blk tree.token_ids[maybe_comma] == .Comma;
- };
-
- const lparen = tree.nextToken(builtin_call.builtin_token);
-
- if (!src_params_trailing_comma) {
- try renderToken(tree, ais, lparen, Space.None); // (
-
- // render all on one line, no trailing comma
- const params = builtin_call.params();
- for (params) |param_node, i| {
- const maybe_comment = param_node.firstToken() - 1;
- if (param_node.*.tag == .MultilineStringLiteral or tree.token_ids[maybe_comment] == .LineComment) {
- ais.pushIndentOneShot();
- }
- try renderExpression(allocator, ais, tree, param_node, Space.None);
-
- if (i + 1 < params.len) {
- const comma_token = tree.nextToken(param_node.lastToken());
- try renderToken(tree, ais, comma_token, Space.Space); // ,
- }
- }
- } else {
- // one param per line
- ais.pushIndent();
- defer ais.popIndent();
- try renderToken(tree, ais, lparen, Space.Newline); // (
-
- for (builtin_call.params()) |param_node| {
- try renderExpression(allocator, ais, tree, param_node, Space.Comma);
- }
- }
-
- return renderToken(tree, ais, builtin_call.rparen_token, space); // )
- },
-
- .FnProto => {
- const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base);
-
- if (fn_proto.getVisibToken()) |visib_token_index| {
- const visib_token = tree.token_ids[visib_token_index];
- assert(visib_token == .Keyword_pub or visib_token == .Keyword_export);
-
- try renderToken(tree, ais, visib_token_index, Space.Space); // pub
- }
-
- if (fn_proto.getExternExportInlineToken()) |extern_export_inline_token| {
- if (fn_proto.getIsExternPrototype() == null)
- try renderToken(tree, ais, extern_export_inline_token, Space.Space); // extern/export/inline
- }
-
- if (fn_proto.getLibName()) |lib_name| {
- try renderExpression(allocator, ais, tree, lib_name, Space.Space);
- }
-
- const lparen = if (fn_proto.getNameToken()) |name_token| blk: {
- try renderToken(tree, ais, fn_proto.fn_token, Space.Space); // fn
- try renderToken(tree, ais, name_token, Space.None); // name
- break :blk tree.nextToken(name_token);
- } else blk: {
- try renderToken(tree, ais, fn_proto.fn_token, Space.Space); // fn
- break :blk tree.nextToken(fn_proto.fn_token);
- };
- assert(tree.token_ids[lparen] == .LParen);
-
- const rparen = tree.prevToken(
- // the first token for the annotation expressions is the left
- // parenthesis, hence the need for two prevToken
- if (fn_proto.getAlignExpr()) |align_expr|
- tree.prevToken(tree.prevToken(align_expr.firstToken()))
- else if (fn_proto.getSectionExpr()) |section_expr|
- tree.prevToken(tree.prevToken(section_expr.firstToken()))
- else if (fn_proto.getCallconvExpr()) |callconv_expr|
- tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
- else switch (fn_proto.return_type) {
- .Explicit => |node| node.firstToken(),
- .InferErrorSet => |node| tree.prevToken(node.firstToken()),
- .Invalid => unreachable,
- },
- );
- assert(tree.token_ids[rparen] == .RParen);
-
- const src_params_trailing_comma = blk: {
- const maybe_comma = tree.token_ids[rparen - 1];
- break :blk maybe_comma == .Comma or maybe_comma == .LineComment;
- };
-
- if (!src_params_trailing_comma) {
- try renderToken(tree, ais, lparen, Space.None); // (
-
- // render all on one line, no trailing comma
- for (fn_proto.params()) |param_decl, i| {
- try renderParamDecl(allocator, ais, tree, param_decl, Space.None);
-
- if (i + 1 < fn_proto.params_len or fn_proto.getVarArgsToken() != null) {
- const comma = tree.nextToken(param_decl.lastToken());
- try renderToken(tree, ais, comma, Space.Space); // ,
- }
- }
- if (fn_proto.getVarArgsToken()) |var_args_token| {
- try renderToken(tree, ais, var_args_token, Space.None);
- }
- } else {
- // one param per line
- ais.pushIndent();
- defer ais.popIndent();
- try renderToken(tree, ais, lparen, Space.Newline); // (
-
- for (fn_proto.params()) |param_decl| {
- try renderParamDecl(allocator, ais, tree, param_decl, Space.Comma);
- }
- if (fn_proto.getVarArgsToken()) |var_args_token| {
- try renderToken(tree, ais, var_args_token, Space.Comma);
- }
- }
-
- try renderToken(tree, ais, rparen, Space.Space); // )
-
- if (fn_proto.getAlignExpr()) |align_expr| {
- const align_rparen = tree.nextToken(align_expr.lastToken());
- const align_lparen = tree.prevToken(align_expr.firstToken());
- const align_kw = tree.prevToken(align_lparen);
-
- try renderToken(tree, ais, align_kw, Space.None); // align
- try renderToken(tree, ais, align_lparen, Space.None); // (
- try renderExpression(allocator, ais, tree, align_expr, Space.None);
- try renderToken(tree, ais, align_rparen, Space.Space); // )
- }
-
- if (fn_proto.getSectionExpr()) |section_expr| {
- const section_rparen = tree.nextToken(section_expr.lastToken());
- const section_lparen = tree.prevToken(section_expr.firstToken());
- const section_kw = tree.prevToken(section_lparen);
-
- try renderToken(tree, ais, section_kw, Space.None); // section
- try renderToken(tree, ais, section_lparen, Space.None); // (
- try renderExpression(allocator, ais, tree, section_expr, Space.None);
- try renderToken(tree, ais, section_rparen, Space.Space); // )
- }
-
- if (fn_proto.getCallconvExpr()) |callconv_expr| {
- const callconv_rparen = tree.nextToken(callconv_expr.lastToken());
- const callconv_lparen = tree.prevToken(callconv_expr.firstToken());
- const callconv_kw = tree.prevToken(callconv_lparen);
-
- try renderToken(tree, ais, callconv_kw, Space.None); // callconv
- try renderToken(tree, ais, callconv_lparen, Space.None); // (
- try renderExpression(allocator, ais, tree, callconv_expr, Space.None);
- try renderToken(tree, ais, callconv_rparen, Space.Space); // )
- } else if (fn_proto.getIsExternPrototype() != null) {
- try ais.writer().writeAll("callconv(.C) ");
- } else if (fn_proto.getIsAsync() != null) {
- try ais.writer().writeAll("callconv(.Async) ");
- }
-
- switch (fn_proto.return_type) {
- .Explicit => |node| {
- return renderExpression(allocator, ais, tree, node, space);
- },
- .InferErrorSet => |node| {
- try renderToken(tree, ais, tree.prevToken(node.firstToken()), Space.None); // !
- return renderExpression(allocator, ais, tree, node, space);
- },
- .Invalid => unreachable,
- }
- },
-
- .AnyFrameType => {
- const anyframe_type = @fieldParentPtr(ast.Node.AnyFrameType, "base", base);
-
- if (anyframe_type.result) |result| {
- try renderToken(tree, ais, anyframe_type.anyframe_token, Space.None); // anyframe
- try renderToken(tree, ais, result.arrow_token, Space.None); // ->
- return renderExpression(allocator, ais, tree, result.return_type, space);
- } else {
- return renderToken(tree, ais, anyframe_type.anyframe_token, space); // anyframe
- }
- },
-
- .DocComment => unreachable, // doc comments are attached to nodes
-
- .Switch => {
- const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
-
- try renderToken(tree, ais, switch_node.switch_token, Space.Space); // switch
- try renderToken(tree, ais, tree.nextToken(switch_node.switch_token), Space.None); // (
-
- const rparen = tree.nextToken(switch_node.expr.lastToken());
- const lbrace = tree.nextToken(rparen);
-
- if (switch_node.cases_len == 0) {
- try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
- try renderToken(tree, ais, rparen, Space.Space); // )
- try renderToken(tree, ais, lbrace, Space.None); // {
- return renderToken(tree, ais, switch_node.rbrace, space); // }
- }
-
- try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
- try renderToken(tree, ais, rparen, Space.Space); // )
-
- {
ais.pushIndentNextLine();
- defer ais.popIndent();
- try renderToken(tree, ais, lbrace, Space.Newline); // {
-
- const cases = switch_node.cases();
- for (cases) |node, i| {
- try renderExpression(allocator, ais, tree, node, Space.Comma);
-
- if (i + 1 < cases.len) {
- try renderExtraNewline(tree, ais, cases[i + 1]);
- }
- }
- }
-
- return renderToken(tree, ais, switch_node.rbrace, space); // }
- },
-
- .SwitchCase => {
- const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
-
- assert(switch_case.items_len != 0);
- const src_has_trailing_comma = blk: {
- const last_node = switch_case.items()[switch_case.items_len - 1];
- const maybe_comma = tree.nextToken(last_node.lastToken());
- break :blk tree.token_ids[maybe_comma] == .Comma;
- };
-
- if (switch_case.items_len == 1 or !src_has_trailing_comma) {
- const items = switch_case.items();
- for (items) |node, i| {
- if (i + 1 < items.len) {
- try renderExpression(allocator, ais, tree, node, Space.None);
-
- const comma_token = tree.nextToken(node.lastToken());
- try renderToken(tree, ais, comma_token, Space.Space); // ,
- try renderExtraNewline(tree, ais, items[i + 1]);
- } else {
- try renderExpression(allocator, ais, tree, node, Space.Space);
- }
- }
- } else {
- const items = switch_case.items();
- for (items) |node, i| {
- if (i + 1 < items.len) {
- try renderExpression(allocator, ais, tree, node, Space.None);
-
- const comma_token = tree.nextToken(node.lastToken());
- try renderToken(tree, ais, comma_token, Space.Newline); // ,
- try renderExtraNewline(tree, ais, items[i + 1]);
- } else {
- try renderExpression(allocator, ais, tree, node, Space.Comma);
- }
- }
- }
-
- try renderToken(tree, ais, switch_case.arrow_token, Space.Space); // =>
-
- if (switch_case.payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Space);
- }
-
- return renderExpression(allocator, ais, tree, switch_case.expr, space);
- },
- .SwitchElse => {
- const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
- return renderToken(tree, ais, switch_else.token, space);
- },
- .Else => {
- const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
-
- const body_is_block = nodeIsBlock(else_node.body);
- const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
-
- const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
- try renderToken(tree, ais, else_node.else_token, after_else_space);
- if (else_node.payload) |payload| {
- const payload_space = if (same_line) Space.Space else Space.Newline;
- try renderExpression(allocator, ais, tree, payload, payload_space);
- }
-
- if (same_line) {
- return renderExpression(allocator, ais, tree, else_node.body, space);
- } else {
- ais.pushIndent();
- defer ais.popIndent();
- return renderExpression(allocator, ais, tree, else_node.body, space);
- }
- },
-
- .While => {
- const while_node = @fieldParentPtr(ast.Node.While, "base", base);
-
- if (while_node.label) |label| {
- try renderToken(tree, ais, label, Space.None); // label
- try renderToken(tree, ais, tree.nextToken(label), Space.Space); // :
- }
-
- if (while_node.inline_token) |inline_token| {
- try renderToken(tree, ais, inline_token, Space.Space); // inline
- }
-
- try renderToken(tree, ais, while_node.while_token, Space.Space); // while
- try renderToken(tree, ais, tree.nextToken(while_node.while_token), Space.None); // (
- try renderExpression(allocator, ais, tree, while_node.condition, Space.None);
-
- const cond_rparen = tree.nextToken(while_node.condition.lastToken());
-
- const body_is_block = nodeIsBlock(while_node.body);
-
- var block_start_space: Space = undefined;
- var after_body_space: Space = undefined;
-
- if (body_is_block) {
- block_start_space = Space.BlockStart;
- after_body_space = if (while_node.@"else" == null) space else Space.SpaceOrOutdent;
- } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
- block_start_space = Space.Space;
- after_body_space = if (while_node.@"else" == null) space else Space.Space;
- } else {
- block_start_space = Space.Newline;
- after_body_space = if (while_node.@"else" == null) space else Space.Newline;
- }
-
- {
- const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
- try renderToken(tree, ais, cond_rparen, rparen_space); // )
- }
-
- if (while_node.payload) |payload| {
- const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
- try renderExpression(allocator, ais, tree, payload, payload_space);
- }
-
- if (while_node.continue_expr) |continue_expr| {
- const rparen = tree.nextToken(continue_expr.lastToken());
- const lparen = tree.prevToken(continue_expr.firstToken());
- const colon = tree.prevToken(lparen);
-
- try renderToken(tree, ais, colon, Space.Space); // :
- try renderToken(tree, ais, lparen, Space.None); // (
-
- try renderExpression(allocator, ais, tree, continue_expr, Space.None);
-
- try renderToken(tree, ais, rparen, block_start_space); // )
- }
-
- {
- if (!body_is_block) ais.pushIndent();
- defer if (!body_is_block) ais.popIndent();
- try renderExpression(allocator, ais, tree, while_node.body, after_body_space);
- }
-
- if (while_node.@"else") |@"else"| {
- return renderExpression(allocator, ais, tree, &@"else".base, space);
- }
- },
-
- .For => {
- const for_node = @fieldParentPtr(ast.Node.For, "base", base);
-
- if (for_node.label) |label| {
- try renderToken(tree, ais, label, Space.None); // label
- try renderToken(tree, ais, tree.nextToken(label), Space.Space); // :
- }
-
- if (for_node.inline_token) |inline_token| {
- try renderToken(tree, ais, inline_token, Space.Space); // inline
- }
-
- try renderToken(tree, ais, for_node.for_token, Space.Space); // for
- try renderToken(tree, ais, tree.nextToken(for_node.for_token), Space.None); // (
- try renderExpression(allocator, ais, tree, for_node.array_expr, Space.None);
-
- const rparen = tree.nextToken(for_node.array_expr.lastToken());
+ try renderToken(ais, tree, lbrace, .Newline);
- const body_is_block = for_node.body.tag.isBlock();
- const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());
- const body_on_same_line = body_is_block or src_one_line_to_body;
+ for (statements) |statement, i| {
+ try renderStatement(ais, tree, statement);
- try renderToken(tree, ais, rparen, Space.Space); // )
-
- const space_after_payload = if (body_on_same_line) Space.Space else Space.Newline;
- try renderExpression(allocator, ais, tree, for_node.payload, space_after_payload); // |x|
-
- const space_after_body = blk: {
- if (for_node.@"else") |@"else"| {
- const src_one_line_to_else = tree.tokensOnSameLine(rparen, @"else".firstToken());
- if (body_is_block or src_one_line_to_else) {
- break :blk Space.Space;
- } else {
- break :blk Space.Newline;
+ if (i + 1 < statements.len) {
+ try renderExtraNewline(tree, ais, statements[i + 1]);
}
- } else {
- break :blk space;
}
- };
-
- {
- if (!body_on_same_line) ais.pushIndent();
- defer if (!body_on_same_line) ais.popIndent();
- try renderExpression(allocator, ais, tree, for_node.body, space_after_body); // { body }
- }
-
- if (for_node.@"else") |@"else"| {
- return renderExpression(allocator, ais, tree, &@"else".base, space); // else
+ ais.popIndent();
+ const rbrace = tree.lastToken(statements[statements.len - 1]) + 1;
+ return renderToken(ais, tree, rbrace, space);
}
},
- .If => {
- const if_node = @fieldParentPtr(ast.Node.If, "base", base);
-
- const lparen = tree.nextToken(if_node.if_token);
- const rparen = tree.nextToken(if_node.condition.lastToken());
-
- try renderToken(tree, ais, if_node.if_token, Space.Space); // if
- try renderToken(tree, ais, lparen, Space.None); // (
-
- try renderExpression(allocator, ais, tree, if_node.condition, Space.None); // condition
-
- const body_is_if_block = if_node.body.tag == .If;
- const body_is_block = nodeIsBlock(if_node.body);
-
- if (body_is_if_block) {
- try renderExtraNewline(tree, ais, if_node.body);
- } else if (body_is_block) {
- const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
- try renderToken(tree, ais, rparen, after_rparen_space); // )
-
- if (if_node.payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.BlockStart); // |x|
- }
-
- if (if_node.@"else") |@"else"| {
- try renderExpression(allocator, ais, tree, if_node.body, Space.SpaceOrOutdent);
- return renderExpression(allocator, ais, tree, &@"else".base, space);
- } else {
- return renderExpression(allocator, ais, tree, if_node.body, space);
- }
- }
-
- const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken());
-
- if (src_has_newline) {
- const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space;
-
- {
- ais.pushIndent();
- defer ais.popIndent();
- try renderToken(tree, ais, rparen, after_rparen_space); // )
- }
-
- if (if_node.payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Newline);
- }
-
- if (if_node.@"else") |@"else"| {
- const else_is_block = nodeIsBlock(@"else".body);
-
- {
- ais.pushIndent();
- defer ais.popIndent();
- try renderExpression(allocator, ais, tree, if_node.body, Space.Newline);
- }
-
- if (else_is_block) {
- try renderToken(tree, ais, @"else".else_token, Space.Space); // else
-
- if (@"else".payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Space);
- }
-
- return renderExpression(allocator, ais, tree, @"else".body, space);
- } else {
- const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;
- try renderToken(tree, ais, @"else".else_token, after_else_space); // else
-
- if (@"else".payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Newline);
- }
-
- ais.pushIndent();
- defer ais.popIndent();
- return renderExpression(allocator, ais, tree, @"else".body, space);
- }
- } else {
- ais.pushIndent();
- defer ais.popIndent();
- return renderExpression(allocator, ais, tree, if_node.body, space);
- }
- }
-
- // Single line if statement
-
- try renderToken(tree, ais, rparen, Space.Space); // )
-
- if (if_node.payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Space);
- }
+ //.Defer => {
+ // const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
- if (if_node.@"else") |@"else"| {
- try renderExpression(allocator, ais, tree, if_node.body, Space.Space);
- try renderToken(tree, ais, @"else".else_token, Space.Space);
-
- if (@"else".payload) |payload| {
- try renderExpression(allocator, ais, tree, payload, Space.Space);
- }
-
- return renderExpression(allocator, ais, tree, @"else".body, space);
- } else {
- return renderExpression(allocator, ais, tree, if_node.body, space);
- }
- },
-
- .Asm => {
- const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
-
- try renderToken(tree, ais, asm_node.asm_token, Space.Space); // asm
-
- if (asm_node.volatile_token) |volatile_token| {
- try renderToken(tree, ais, volatile_token, Space.Space); // volatile
- try renderToken(tree, ais, tree.nextToken(volatile_token), Space.None); // (
- } else {
- try renderToken(tree, ais, tree.nextToken(asm_node.asm_token), Space.None); // (
- }
-
- asmblk: {
- ais.pushIndent();
- defer ais.popIndent();
-
- if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
- try renderExpression(allocator, ais, tree, asm_node.template, Space.None);
- break :asmblk;
- }
-
- try renderExpression(allocator, ais, tree, asm_node.template, Space.Newline);
-
- ais.setIndentDelta(asm_indent_delta);
- defer ais.setIndentDelta(indent_delta);
-
- const colon1 = tree.nextToken(asm_node.template.lastToken());
-
- const colon2 = if (asm_node.outputs.len == 0) blk: {
- try renderToken(tree, ais, colon1, Space.Newline); // :
-
- break :blk tree.nextToken(colon1);
- } else blk: {
- try renderToken(tree, ais, colon1, Space.Space); // :
-
- ais.pushIndent();
- defer ais.popIndent();
-
- for (asm_node.outputs) |*asm_output, i| {
- if (i + 1 < asm_node.outputs.len) {
- const next_asm_output = asm_node.outputs[i + 1];
- try renderAsmOutput(allocator, ais, tree, asm_output, Space.None);
-
- const comma = tree.prevToken(next_asm_output.firstToken());
- try renderToken(tree, ais, comma, Space.Newline); // ,
- try renderExtraNewlineToken(tree, ais, next_asm_output.firstToken());
- } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
- try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
- break :asmblk;
- } else {
- try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
- const comma_or_colon = tree.nextToken(asm_output.lastToken());
- break :blk switch (tree.token_ids[comma_or_colon]) {
- .Comma => tree.nextToken(comma_or_colon),
- else => comma_or_colon,
- };
- }
- }
- unreachable;
- };
-
- const colon3 = if (asm_node.inputs.len == 0) blk: {
- try renderToken(tree, ais, colon2, Space.Newline); // :
- break :blk tree.nextToken(colon2);
- } else blk: {
- try renderToken(tree, ais, colon2, Space.Space); // :
- ais.pushIndent();
- defer ais.popIndent();
- for (asm_node.inputs) |*asm_input, i| {
- if (i + 1 < asm_node.inputs.len) {
- const next_asm_input = &asm_node.inputs[i + 1];
- try renderAsmInput(allocator, ais, tree, asm_input, Space.None);
-
- const comma = tree.prevToken(next_asm_input.firstToken());
- try renderToken(tree, ais, comma, Space.Newline); // ,
- try renderExtraNewlineToken(tree, ais, next_asm_input.firstToken());
- } else if (asm_node.clobbers.len == 0) {
- try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
- break :asmblk;
- } else {
- try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
- const comma_or_colon = tree.nextToken(asm_input.lastToken());
- break :blk switch (tree.token_ids[comma_or_colon]) {
- .Comma => tree.nextToken(comma_or_colon),
- else => comma_or_colon,
- };
- }
- }
- unreachable;
- };
-
- try renderToken(tree, ais, colon3, Space.Space); // :
- ais.pushIndent();
- defer ais.popIndent();
- for (asm_node.clobbers) |clobber_node, i| {
- if (i + 1 >= asm_node.clobbers.len) {
- try renderExpression(allocator, ais, tree, clobber_node, Space.Newline);
- break :asmblk;
- } else {
- try renderExpression(allocator, ais, tree, clobber_node, Space.None);
- const comma = tree.nextToken(clobber_node.lastToken());
- try renderToken(tree, ais, comma, Space.Space); // ,
- }
- }
- }
-
- return renderToken(tree, ais, asm_node.rparen, space);
- },
-
- .EnumLiteral => {
- const enum_literal = @fieldParentPtr(ast.Node.EnumLiteral, "base", base);
-
- try renderToken(tree, ais, enum_literal.dot, Space.None); // .
- return renderToken(tree, ais, enum_literal.name, space); // name
+ // try renderToken(ais, tree, defer_node.defer_token, Space.Space);
+ // if (defer_node.payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Space);
+ // }
+ // return renderExpression(allocator, ais, tree, defer_node.expr, space);
+ //},
+ .Comptime => {
+ const comptime_token = tree.nodes.items(.main_token)[node];
+ const block = tree.nodes.items(.data)[node].lhs;
+ try renderToken(ais, tree, comptime_token, .Space);
+ return renderExpression(ais, tree, block, space);
},
-
- .ContainerField,
- .Root,
- .VarDecl,
- .Use,
- .TestDecl,
- => unreachable,
+ //.Nosuspend => {
+ // const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base);
+ // if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) {
+ // // TODO: remove this
+ // try ais.writer().writeAll("nosuspend ");
+ // } else {
+ // try renderToken(ais, tree, nosuspend_node.nosuspend_token, Space.Space);
+ // }
+ // return renderExpression(allocator, ais, tree, nosuspend_node.expr, space);
+ //},
+
+ //.Suspend => {
+ // const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
+
+ // if (suspend_node.body) |body| {
+ // try renderToken(ais, tree, suspend_node.suspend_token, Space.Space);
+ // return renderExpression(allocator, ais, tree, body, space);
+ // } else {
+ // return renderToken(ais, tree, suspend_node.suspend_token, space);
+ // }
+ //},
+
+ //.Catch => {
+ // const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base);
+
+ // const op_space = Space.Space;
+ // try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
+
+ // const after_op_space = blk: {
+ // const same_line = tree.tokensOnSameLine(infix_op_node.op_token, tree.nextToken(infix_op_node.op_token));
+ // break :blk if (same_line) op_space else Space.Newline;
+ // };
+
+ // try renderToken(ais, tree, infix_op_node.op_token, after_op_space);
+
+ // if (infix_op_node.payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Space);
+ // }
+
+ // ais.pushIndentOneShot();
+ // return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
+ //},
+
+ //.Add,
+ //.AddWrap,
+ //.ArrayCat,
+ //.ArrayMult,
+ //.Assign,
+ //.AssignBitAnd,
+ //.AssignBitOr,
+ //.AssignBitShiftLeft,
+ //.AssignBitShiftRight,
+ //.AssignBitXor,
+ //.AssignDiv,
+ //.AssignSub,
+ //.AssignSubWrap,
+ //.AssignMod,
+ //.AssignAdd,
+ //.AssignAddWrap,
+ //.AssignMul,
+ //.AssignMulWrap,
+ //.BangEqual,
+ //.BitAnd,
+ //.BitOr,
+ //.BitShiftLeft,
+ //.BitShiftRight,
+ //.BitXor,
+ //.BoolAnd,
+ //.BoolOr,
+ //.Div,
+ //.EqualEqual,
+ //.ErrorUnion,
+ //.GreaterOrEqual,
+ //.GreaterThan,
+ //.LessOrEqual,
+ //.LessThan,
+ //.MergeErrorSets,
+ //.Mod,
+ //.Mul,
+ //.MulWrap,
+ //.Period,
+ //.Range,
+ //.Sub,
+ //.SubWrap,
+ //.OrElse,
+ //=> {
+ // const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base);
+
+ // const op_space = switch (base.tag) {
+ // .Period, .ErrorUnion, .Range => Space.None,
+ // else => Space.Space,
+ // };
+ // try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
+
+ // const after_op_space = blk: {
+ // const loc = tree.tokenLocation(tree.token_locs[infix_op_node.op_token].end, tree.nextToken(infix_op_node.op_token));
+ // break :blk if (loc.line == 0) op_space else Space.Newline;
+ // };
+
+ // {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, infix_op_node.op_token, after_op_space);
+ // }
+ // ais.pushIndentOneShot();
+ // return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
+ //},
+
+ //.BitNot,
+ //.BoolNot,
+ //.Negation,
+ //.NegationWrap,
+ //.OptionalType,
+ //.AddressOf,
+ //=> {
+ // const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
+ // try renderToken(ais, tree, casted_node.op_token, Space.None);
+ // return renderExpression(allocator, ais, tree, casted_node.rhs, space);
+ //},
+
+ //.Try,
+ //.Resume,
+ //.Await,
+ //=> {
+ // const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
+ // try renderToken(ais, tree, casted_node.op_token, Space.Space);
+ // return renderExpression(allocator, ais, tree, casted_node.rhs, space);
+ //},
+
+ //.ArrayType => {
+ // const array_type = @fieldParentPtr(ast.Node.ArrayType, "base", base);
+ // return renderArrayType(
+ // allocator,
+ // ais,
+ // tree,
+ // array_type.op_token,
+ // array_type.rhs,
+ // array_type.len_expr,
+ // null,
+ // space,
+ // );
+ //},
+ //.ArrayTypeSentinel => {
+ // const array_type = @fieldParentPtr(ast.Node.ArrayTypeSentinel, "base", base);
+ // return renderArrayType(
+ // allocator,
+ // ais,
+ // tree,
+ // array_type.op_token,
+ // array_type.rhs,
+ // array_type.len_expr,
+ // array_type.sentinel,
+ // space,
+ // );
+ //},
+
+ //.PtrType => {
+ // const ptr_type = @fieldParentPtr(ast.Node.PtrType, "base", base);
+ // const op_tok_id = tree.token_tags[ptr_type.op_token];
+ // switch (op_tok_id) {
+ // .Asterisk, .AsteriskAsterisk => try ais.writer().writeByte('*'),
+ // .LBracket => if (tree.token_tags[ptr_type.op_token + 2] == .Identifier)
+ // try ais.writer().writeAll("[*c")
+ // else
+ // try ais.writer().writeAll("[*"),
+ // else => unreachable,
+ // }
+ // if (ptr_type.ptr_info.sentinel) |sentinel| {
+ // const colon_token = tree.prevToken(sentinel.firstToken());
+ // try renderToken(ais, tree, colon_token, Space.None); // :
+ // const sentinel_space = switch (op_tok_id) {
+ // .LBracket => Space.None,
+ // else => Space.Space,
+ // };
+ // try renderExpression(allocator, ais, tree, sentinel, sentinel_space);
+ // }
+ // switch (op_tok_id) {
+ // .Asterisk, .AsteriskAsterisk => {},
+ // .LBracket => try ais.writer().writeByte(']'),
+ // else => unreachable,
+ // }
+ // if (ptr_type.ptr_info.allowzero_token) |allowzero_token| {
+ // try renderToken(ais, tree, allowzero_token, Space.Space); // allowzero
+ // }
+ // if (ptr_type.ptr_info.align_info) |align_info| {
+ // const lparen_token = tree.prevToken(align_info.node.firstToken());
+ // const align_token = tree.prevToken(lparen_token);
+
+ // try renderToken(ais, tree, align_token, Space.None); // align
+ // try renderToken(ais, tree, lparen_token, Space.None); // (
+
+ // try renderExpression(allocator, ais, tree, align_info.node, Space.None);
+
+ // if (align_info.bit_range) |bit_range| {
+ // const colon1 = tree.prevToken(bit_range.start.firstToken());
+ // const colon2 = tree.prevToken(bit_range.end.firstToken());
+
+ // try renderToken(ais, tree, colon1, Space.None); // :
+ // try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
+ // try renderToken(ais, tree, colon2, Space.None); // :
+ // try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
+
+ // const rparen_token = tree.nextToken(bit_range.end.lastToken());
+ // try renderToken(ais, tree, rparen_token, Space.Space); // )
+ // } else {
+ // const rparen_token = tree.nextToken(align_info.node.lastToken());
+ // try renderToken(ais, tree, rparen_token, Space.Space); // )
+ // }
+ // }
+ // if (ptr_type.ptr_info.const_token) |const_token| {
+ // try renderToken(ais, tree, const_token, Space.Space); // const
+ // }
+ // if (ptr_type.ptr_info.volatile_token) |volatile_token| {
+ // try renderToken(ais, tree, volatile_token, Space.Space); // volatile
+ // }
+ // return renderExpression(allocator, ais, tree, ptr_type.rhs, space);
+ //},
+
+ //.SliceType => {
+ // const slice_type = @fieldParentPtr(ast.Node.SliceType, "base", base);
+ // try renderToken(ais, tree, slice_type.op_token, Space.None); // [
+ // if (slice_type.ptr_info.sentinel) |sentinel| {
+ // const colon_token = tree.prevToken(sentinel.firstToken());
+ // try renderToken(ais, tree, colon_token, Space.None); // :
+ // try renderExpression(allocator, ais, tree, sentinel, Space.None);
+ // try renderToken(ais, tree, tree.nextToken(sentinel.lastToken()), Space.None); // ]
+ // } else {
+ // try renderToken(ais, tree, tree.nextToken(slice_type.op_token), Space.None); // ]
+ // }
+
+ // if (slice_type.ptr_info.allowzero_token) |allowzero_token| {
+ // try renderToken(ais, tree, allowzero_token, Space.Space); // allowzero
+ // }
+ // if (slice_type.ptr_info.align_info) |align_info| {
+ // const lparen_token = tree.prevToken(align_info.node.firstToken());
+ // const align_token = tree.prevToken(lparen_token);
+
+ // try renderToken(ais, tree, align_token, Space.None); // align
+ // try renderToken(ais, tree, lparen_token, Space.None); // (
+
+ // try renderExpression(allocator, ais, tree, align_info.node, Space.None);
+
+ // if (align_info.bit_range) |bit_range| {
+ // const colon1 = tree.prevToken(bit_range.start.firstToken());
+ // const colon2 = tree.prevToken(bit_range.end.firstToken());
+
+ // try renderToken(ais, tree, colon1, Space.None); // :
+ // try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
+ // try renderToken(ais, tree, colon2, Space.None); // :
+ // try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
+
+ // const rparen_token = tree.nextToken(bit_range.end.lastToken());
+ // try renderToken(ais, tree, rparen_token, Space.Space); // )
+ // } else {
+ // const rparen_token = tree.nextToken(align_info.node.lastToken());
+ // try renderToken(ais, tree, rparen_token, Space.Space); // )
+ // }
+ // }
+ // if (slice_type.ptr_info.const_token) |const_token| {
+ // try renderToken(ais, tree, const_token, Space.Space);
+ // }
+ // if (slice_type.ptr_info.volatile_token) |volatile_token| {
+ // try renderToken(ais, tree, volatile_token, Space.Space);
+ // }
+ // return renderExpression(allocator, ais, tree, slice_type.rhs, space);
+ //},
+
+ //.ArrayInitializer, .ArrayInitializerDot => {
+ // var rtoken: ast.TokenIndex = undefined;
+ // var exprs: []ast.Node.Index = undefined;
+ // const lhs: union(enum) { dot: ast.TokenIndex, node: ast.Node.Index } = switch (base.tag) {
+ // .ArrayInitializerDot => blk: {
+ // const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base);
+ // rtoken = casted.rtoken;
+ // exprs = casted.list();
+ // break :blk .{ .dot = casted.dot };
+ // },
+ // .ArrayInitializer => blk: {
+ // const casted = @fieldParentPtr(ast.Node.ArrayInitializer, "base", base);
+ // rtoken = casted.rtoken;
+ // exprs = casted.list();
+ // break :blk .{ .node = casted.lhs };
+ // },
+ // else => unreachable,
+ // };
+
+ // const lbrace = switch (lhs) {
+ // .dot => |dot| tree.nextToken(dot),
+ // .node => |node| tree.nextToken(node.lastToken()),
+ // };
+
+ // switch (lhs) {
+ // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
+ // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
+ // }
+
+ // if (exprs.len == 0) {
+ // try renderToken(ais, tree, lbrace, Space.None);
+ // return renderToken(ais, tree, rtoken, space);
+ // }
+
+ // if (exprs.len == 1 and exprs[0].tag != .MultilineStringLiteral and tree.token_tags[exprs[0].*.lastToken() + 1] == .RBrace) {
+ // const expr = exprs[0];
+
+ // try renderToken(ais, tree, lbrace, Space.None);
+ // try renderExpression(allocator, ais, tree, expr, Space.None);
+ // return renderToken(ais, tree, rtoken, space);
+ // }
+
+ // // scan to find row size
+ // if (rowSize(tree, exprs, rtoken) != null) {
+ // {
+ // ais.pushIndentNextLine();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, lbrace, Space.Newline);
+
+ // var expr_index: usize = 0;
+ // while (rowSize(tree, exprs[expr_index..], rtoken)) |row_size| {
+ // const row_exprs = exprs[expr_index..];
+ // // A place to store the width of each expression and its column's maximum
+ // var widths = try allocator.alloc(usize, row_exprs.len + row_size);
+ // defer allocator.free(widths);
+ // mem.set(usize, widths, 0);
+
+ // var expr_newlines = try allocator.alloc(bool, row_exprs.len);
+ // defer allocator.free(expr_newlines);
+ // mem.set(bool, expr_newlines, false);
+
+ // var expr_widths = widths[0 .. widths.len - row_size];
+ // var column_widths = widths[widths.len - row_size ..];
+
+ // // Find next row with trailing comment (if any) to end the current section
+ // var section_end = sec_end: {
+ // var this_line_first_expr: usize = 0;
+ // var this_line_size = rowSize(tree, row_exprs, rtoken);
+ // for (row_exprs) |expr, i| {
+ // // Ignore comment on first line of this section
+ // if (i == 0 or tree.tokensOnSameLine(row_exprs[0].firstToken(), expr.lastToken())) continue;
+ // // Track start of line containing comment
+ // if (!tree.tokensOnSameLine(row_exprs[this_line_first_expr].firstToken(), expr.lastToken())) {
+ // this_line_first_expr = i;
+ // this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rtoken);
+ // }
+
+ // const maybe_comma = expr.lastToken() + 1;
+ // const maybe_comment = expr.lastToken() + 2;
+ // if (maybe_comment < tree.token_tags.len) {
+ // if (tree.token_tags[maybe_comma] == .Comma and
+ // tree.token_tags[maybe_comment] == .LineComment and
+ // tree.tokensOnSameLine(expr.lastToken(), maybe_comment))
+ // {
+ // var comment_token_loc = tree.token_locs[maybe_comment];
+ // const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2;
+ // if (!comment_is_empty) {
+ // // Found row ending in comment
+ // break :sec_end i - this_line_size.? + 1;
+ // }
+ // }
+ // }
+ // }
+ // break :sec_end row_exprs.len;
+ // };
+ // expr_index += section_end;
+
+ // const section_exprs = row_exprs[0..section_end];
+
+ // // Null stream for counting the printed length of each expression
+ // var line_find_stream = std.io.findByteWriter('\n', std.io.null_writer);
+ // var counting_stream = std.io.countingWriter(line_find_stream.writer());
+ // var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer());
+
+ // // Calculate size of columns in current section
+ // var column_counter: usize = 0;
+ // var single_line = true;
+ // for (section_exprs) |expr, i| {
+ // if (i + 1 < section_exprs.len) {
+ // counting_stream.bytes_written = 0;
+ // line_find_stream.byte_found = false;
+ // try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
+ // const width = @intCast(usize, counting_stream.bytes_written);
+ // expr_widths[i] = width;
+ // expr_newlines[i] = line_find_stream.byte_found;
+
+ // if (!line_find_stream.byte_found) {
+ // const column = column_counter % row_size;
+ // column_widths[column] = std.math.max(column_widths[column], width);
+
+ // const expr_last_token = expr.*.lastToken() + 1;
+ // const next_expr = section_exprs[i + 1];
+ // const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, next_expr.*.firstToken());
+
+ // column_counter += 1;
+
+ // if (loc.line != 0) single_line = false;
+ // } else {
+ // single_line = false;
+ // column_counter = 0;
+ // }
+ // } else {
+ // counting_stream.bytes_written = 0;
+ // try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
+ // const width = @intCast(usize, counting_stream.bytes_written);
+ // expr_widths[i] = width;
+ // expr_newlines[i] = line_find_stream.byte_found;
+
+ // if (!line_find_stream.byte_found) {
+ // const column = column_counter % row_size;
+ // column_widths[column] = std.math.max(column_widths[column], width);
+ // }
+ // break;
+ // }
+ // }
+
+ // // Render exprs in current section
+ // column_counter = 0;
+ // var last_col_index: usize = row_size - 1;
+ // for (section_exprs) |expr, i| {
+ // if (i + 1 < section_exprs.len) {
+ // const next_expr = section_exprs[i + 1];
+ // try renderExpression(allocator, ais, tree, expr, Space.None);
+
+ // const comma = tree.nextToken(expr.*.lastToken());
+
+ // if (column_counter != last_col_index) {
+ // if (!expr_newlines[i] and !expr_newlines[i + 1]) {
+ // // Neither the current or next expression is multiline
+ // try renderToken(ais, tree, comma, Space.Space); // ,
+ // assert(column_widths[column_counter % row_size] >= expr_widths[i]);
+ // const padding = column_widths[column_counter % row_size] - expr_widths[i];
+ // try ais.writer().writeByteNTimes(' ', padding);
+
+ // column_counter += 1;
+ // continue;
+ // }
+ // }
+ // if (single_line and row_size != 1) {
+ // try renderToken(ais, tree, comma, Space.Space); // ,
+ // continue;
+ // }
+
+ // column_counter = 0;
+ // try renderToken(ais, tree, comma, Space.Newline); // ,
+ // try renderExtraNewline(tree, ais, next_expr);
+ // } else {
+ // const maybe_comma = tree.nextToken(expr.*.lastToken());
+ // if (tree.token_tags[maybe_comma] == .Comma) {
+ // try renderExpression(allocator, ais, tree, expr, Space.None); // ,
+ // try renderToken(ais, tree, maybe_comma, Space.Newline); // ,
+ // } else {
+ // try renderExpression(allocator, ais, tree, expr, Space.Comma); // ,
+ // }
+ // }
+ // }
+
+ // if (expr_index == exprs.len) {
+ // break;
+ // }
+ // }
+ // }
+
+ // return renderToken(ais, tree, rtoken, space);
+ // }
+
+ // // Single line
+ // try renderToken(ais, tree, lbrace, Space.Space);
+ // for (exprs) |expr, i| {
+ // if (i + 1 < exprs.len) {
+ // const next_expr = exprs[i + 1];
+ // try renderExpression(allocator, ais, tree, expr, Space.None);
+ // const comma = tree.nextToken(expr.*.lastToken());
+ // try renderToken(ais, tree, comma, Space.Space); // ,
+ // } else {
+ // try renderExpression(allocator, ais, tree, expr, Space.Space);
+ // }
+ // }
+
+ // return renderToken(ais, tree, rtoken, space);
+ //},
+
+ //.StructInitializer, .StructInitializerDot => {
+ // var rtoken: ast.TokenIndex = undefined;
+ // var field_inits: []ast.Node.Index = undefined;
+ // const lhs: union(enum) { dot: ast.TokenIndex, node: ast.Node.Index } = switch (base.tag) {
+ // .StructInitializerDot => blk: {
+ // const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base);
+ // rtoken = casted.rtoken;
+ // field_inits = casted.list();
+ // break :blk .{ .dot = casted.dot };
+ // },
+ // .StructInitializer => blk: {
+ // const casted = @fieldParentPtr(ast.Node.StructInitializer, "base", base);
+ // rtoken = casted.rtoken;
+ // field_inits = casted.list();
+ // break :blk .{ .node = casted.lhs };
+ // },
+ // else => unreachable,
+ // };
+
+ // const lbrace = switch (lhs) {
+ // .dot => |dot| tree.nextToken(dot),
+ // .node => |node| tree.nextToken(node.lastToken()),
+ // };
+
+ // if (field_inits.len == 0) {
+ // switch (lhs) {
+ // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
+ // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
+ // }
+
+ // {
+ // ais.pushIndentNextLine();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, lbrace, Space.None);
+ // }
+
+ // return renderToken(ais, tree, rtoken, space);
+ // }
+
+ // const src_has_trailing_comma = blk: {
+ // const maybe_comma = tree.prevToken(rtoken);
+ // break :blk tree.token_tags[maybe_comma] == .Comma;
+ // };
+
+ // const src_same_line = blk: {
+ // const loc = tree.tokenLocation(tree.token_locs[lbrace].end, rtoken);
+ // break :blk loc.line == 0;
+ // };
+
+ // const expr_outputs_one_line = blk: {
+ // // render field expressions until a LF is found
+ // for (field_inits) |field_init| {
+ // var find_stream = std.io.findByteWriter('\n', std.io.null_writer);
+ // var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, find_stream.writer());
+
+ // try renderExpression(allocator, &auto_indenting_stream, tree, field_init, Space.None);
+ // if (find_stream.byte_found) break :blk false;
+ // }
+ // break :blk true;
+ // };
+
+ // if (field_inits.len == 1) blk: {
+ // if (field_inits[0].cast(ast.Node.FieldInitializer)) |field_init| {
+ // switch (field_init.expr.tag) {
+ // .StructInitializer,
+ // .StructInitializerDot,
+ // => break :blk,
+ // else => {},
+ // }
+ // }
+
+ // // if the expression outputs to multiline, make this struct multiline
+ // if (!expr_outputs_one_line or src_has_trailing_comma) {
+ // break :blk;
+ // }
+
+ // switch (lhs) {
+ // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
+ // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
+ // }
+ // try renderToken(ais, tree, lbrace, Space.Space);
+ // try renderExpression(allocator, ais, tree, field_inits[0], Space.Space);
+ // return renderToken(ais, tree, rtoken, space);
+ // }
+
+ // if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
+ // // render all on one line, no trailing comma
+ // switch (lhs) {
+ // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
+ // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
+ // }
+ // try renderToken(ais, tree, lbrace, Space.Space);
+
+ // for (field_inits) |field_init, i| {
+ // if (i + 1 < field_inits.len) {
+ // try renderExpression(allocator, ais, tree, field_init, Space.None);
+
+ // const comma = tree.nextToken(field_init.lastToken());
+ // try renderToken(ais, tree, comma, Space.Space);
+ // } else {
+ // try renderExpression(allocator, ais, tree, field_init, Space.Space);
+ // }
+ // }
+
+ // return renderToken(ais, tree, rtoken, space);
+ // }
+
+ // {
+ // switch (lhs) {
+ // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
+ // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
+ // }
+
+ // ais.pushIndentNextLine();
+ // defer ais.popIndent();
+
+ // try renderToken(ais, tree, lbrace, Space.Newline);
+
+ // for (field_inits) |field_init, i| {
+ // if (i + 1 < field_inits.len) {
+ // const next_field_init = field_inits[i + 1];
+ // try renderExpression(allocator, ais, tree, field_init, Space.None);
+
+ // const comma = tree.nextToken(field_init.lastToken());
+ // try renderToken(ais, tree, comma, Space.Newline);
+
+ // try renderExtraNewline(tree, ais, next_field_init);
+ // } else {
+ // try renderExpression(allocator, ais, tree, field_init, Space.Comma);
+ // }
+ // }
+ // }
+
+ // return renderToken(ais, tree, rtoken, space);
+ //},
+
+ //.Call => {
+ // const call = @fieldParentPtr(ast.Node.Call, "base", base);
+ // if (call.async_token) |async_token| {
+ // try renderToken(ais, tree, async_token, Space.Space);
+ // }
+
+ // try renderExpression(allocator, ais, tree, call.lhs, Space.None);
+
+ // const lparen = tree.nextToken(call.lhs.lastToken());
+
+ // if (call.params_len == 0) {
+ // try renderToken(ais, tree, lparen, Space.None);
+ // return renderToken(ais, tree, call.rtoken, space);
+ // }
+
+ // const src_has_trailing_comma = blk: {
+ // const maybe_comma = tree.prevToken(call.rtoken);
+ // break :blk tree.token_tags[maybe_comma] == .Comma;
+ // };
+
+ // if (src_has_trailing_comma) {
+ // {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+
+ // try renderToken(ais, tree, lparen, Space.Newline); // (
+ // const params = call.params();
+ // for (params) |param_node, i| {
+ // if (i + 1 < params.len) {
+ // const next_node = params[i + 1];
+ // try renderExpression(allocator, ais, tree, param_node, Space.None);
+
+ // // Unindent the comma for multiline string literals
+ // const maybe_multiline_string = param_node.firstToken();
+ // const is_multiline_string = tree.token_tags[maybe_multiline_string] == .MultilineStringLiteralLine;
+ // if (is_multiline_string) ais.popIndent();
+ // defer if (is_multiline_string) ais.pushIndent();
+
+ // const comma = tree.nextToken(param_node.lastToken());
+ // try renderToken(ais, tree, comma, Space.Newline); // ,
+ // try renderExtraNewline(tree, ais, next_node);
+ // } else {
+ // try renderExpression(allocator, ais, tree, param_node, Space.Comma);
+ // }
+ // }
+ // }
+ // return renderToken(ais, tree, call.rtoken, space);
+ // }
+
+ // try renderToken(ais, tree, lparen, Space.None); // (
+
+ // const params = call.params();
+ // for (params) |param_node, i| {
+ // const maybe_comment = param_node.firstToken() - 1;
+ // const maybe_multiline_string = param_node.firstToken();
+ // if (tree.token_tags[maybe_multiline_string] == .MultilineStringLiteralLine or tree.token_tags[maybe_comment] == .LineComment) {
+ // ais.pushIndentOneShot();
+ // }
+
+ // try renderExpression(allocator, ais, tree, param_node, Space.None);
+
+ // if (i + 1 < params.len) {
+ // const comma = tree.nextToken(param_node.lastToken());
+ // try renderToken(ais, tree, comma, Space.Space);
+ // }
+ // }
+ // return renderToken(ais, tree, call.rtoken, space); // )
+ //},
+
+ //.ArrayAccess => {
+ // const suffix_op = base.castTag(.ArrayAccess).?;
+
+ // const lbracket = tree.nextToken(suffix_op.lhs.lastToken());
+ // const rbracket = tree.nextToken(suffix_op.index_expr.lastToken());
+
+ // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
+ // try renderToken(ais, tree, lbracket, Space.None); // [
+
+ // const starts_with_comment = tree.token_tags[lbracket + 1] == .LineComment;
+ // const ends_with_comment = tree.token_tags[rbracket - 1] == .LineComment;
+ // {
+ // const new_space = if (ends_with_comment) Space.Newline else Space.None;
+
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // try renderExpression(allocator, ais, tree, suffix_op.index_expr, new_space);
+ // }
+ // if (starts_with_comment) try ais.maybeInsertNewline();
+ // return renderToken(ais, tree, rbracket, space); // ]
+ //},
+
+ //.Slice => {
+ // const suffix_op = base.castTag(.Slice).?;
+ // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
+
+ // const lbracket = tree.prevToken(suffix_op.start.firstToken());
+ // const dotdot = tree.nextToken(suffix_op.start.lastToken());
+
+ // const after_start_space_bool = nodeCausesSliceOpSpace(suffix_op.start) or
+ // (if (suffix_op.end) |end| nodeCausesSliceOpSpace(end) else false);
+ // const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
+ // const after_op_space = if (suffix_op.end != null) after_start_space else Space.None;
+
+ // try renderToken(ais, tree, lbracket, Space.None); // [
+ // try renderExpression(allocator, ais, tree, suffix_op.start, after_start_space);
+ // try renderToken(ais, tree, dotdot, after_op_space); // ..
+ // if (suffix_op.end) |end| {
+ // const after_end_space = if (suffix_op.sentinel != null) Space.Space else Space.None;
+ // try renderExpression(allocator, ais, tree, end, after_end_space);
+ // }
+ // if (suffix_op.sentinel) |sentinel| {
+ // const colon = tree.prevToken(sentinel.firstToken());
+ // try renderToken(ais, tree, colon, Space.None); // :
+ // try renderExpression(allocator, ais, tree, sentinel, Space.None);
+ // }
+ // return renderToken(ais, tree, suffix_op.rtoken, space); // ]
+ //},
+
+ //.Deref => {
+ // const suffix_op = base.castTag(.Deref).?;
+
+ // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
+ // return renderToken(ais, tree, suffix_op.rtoken, space); // .*
+ //},
+ //.UnwrapOptional => {
+ // const suffix_op = base.castTag(.UnwrapOptional).?;
+
+ // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
+ // try renderToken(ais, tree, tree.prevToken(suffix_op.rtoken), Space.None); // .
+ // return renderToken(ais, tree, suffix_op.rtoken, space); // ?
+ //},
+
+ //.Break => {
+ // const flow_expr = base.castTag(.Break).?;
+ // const maybe_rhs = flow_expr.getRHS();
+ // const maybe_label = flow_expr.getLabel();
+
+ // if (maybe_label == null and maybe_rhs == null) {
+ // return renderToken(ais, tree, flow_expr.ltoken, space); // break
+ // }
+
+ // try renderToken(ais, tree, flow_expr.ltoken, Space.Space); // break
+ // if (maybe_label) |label| {
+ // const colon = tree.nextToken(flow_expr.ltoken);
+ // try renderToken(ais, tree, colon, Space.None); // :
+
+ // if (maybe_rhs == null) {
+ // return renderToken(ais, tree, label, space); // label
+ // }
+ // try renderToken(ais, tree, label, Space.Space); // label
+ // }
+ // return renderExpression(allocator, ais, tree, maybe_rhs.?, space);
+ //},
+
+ //.Continue => {
+ // const flow_expr = base.castTag(.Continue).?;
+ // if (flow_expr.getLabel()) |label| {
+ // try renderToken(ais, tree, flow_expr.ltoken, Space.Space); // continue
+ // const colon = tree.nextToken(flow_expr.ltoken);
+ // try renderToken(ais, tree, colon, Space.None); // :
+ // return renderToken(ais, tree, label, space); // label
+ // } else {
+ // return renderToken(ais, tree, flow_expr.ltoken, space); // continue
+ // }
+ //},
+
+ //.Return => {
+ // const flow_expr = base.castTag(.Return).?;
+ // if (flow_expr.getRHS()) |rhs| {
+ // try renderToken(ais, tree, flow_expr.ltoken, Space.Space);
+ // return renderExpression(allocator, ais, tree, rhs, space);
+ // } else {
+ // return renderToken(ais, tree, flow_expr.ltoken, space);
+ // }
+ //},
+
+ //.Payload => {
+ // const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
+
+ // try renderToken(ais, tree, payload.lpipe, Space.None);
+ // try renderExpression(allocator, ais, tree, payload.error_symbol, Space.None);
+ // return renderToken(ais, tree, payload.rpipe, space);
+ //},
+
+ //.PointerPayload => {
+ // const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
+
+ // try renderToken(ais, tree, payload.lpipe, Space.None);
+ // if (payload.ptr_token) |ptr_token| {
+ // try renderToken(ais, tree, ptr_token, Space.None);
+ // }
+ // try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
+ // return renderToken(ais, tree, payload.rpipe, space);
+ //},
+
+ //.PointerIndexPayload => {
+ // const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
+
+ // try renderToken(ais, tree, payload.lpipe, Space.None);
+ // if (payload.ptr_token) |ptr_token| {
+ // try renderToken(ais, tree, ptr_token, Space.None);
+ // }
+ // try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
+
+ // if (payload.index_symbol) |index_symbol| {
+ // const comma = tree.nextToken(payload.value_symbol.lastToken());
+
+ // try renderToken(ais, tree, comma, Space.Space);
+ // try renderExpression(allocator, ais, tree, index_symbol, Space.None);
+ // }
+
+ // return renderToken(ais, tree, payload.rpipe, space);
+ //},
+
+ //.GroupedExpression => {
+ // const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
+
+ // try renderToken(ais, tree, grouped_expr.lparen, Space.None);
+ // {
+ // ais.pushIndentOneShot();
+ // try renderExpression(allocator, ais, tree, grouped_expr.expr, Space.None);
+ // }
+ // return renderToken(ais, tree, grouped_expr.rparen, space);
+ //},
+
+ //.FieldInitializer => {
+ // const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
+
+ // try renderToken(ais, tree, field_init.period_token, Space.None); // .
+ // try renderToken(ais, tree, field_init.name_token, Space.Space); // name
+ // try renderToken(ais, tree, tree.nextToken(field_init.name_token), Space.Space); // =
+ // return renderExpression(allocator, ais, tree, field_init.expr, space);
+ //},
+
+ //.ContainerDecl => {
+ // const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
+
+ // if (container_decl.layout_token) |layout_token| {
+ // try renderToken(ais, tree, layout_token, Space.Space);
+ // }
+
+ // switch (container_decl.init_arg_expr) {
+ // .None => {
+ // try renderToken(ais, tree, container_decl.kind_token, Space.Space); // union
+ // },
+ // .Enum => |enum_tag_type| {
+ // try renderToken(ais, tree, container_decl.kind_token, Space.None); // union
+
+ // const lparen = tree.nextToken(container_decl.kind_token);
+ // const enum_token = tree.nextToken(lparen);
+
+ // try renderToken(ais, tree, lparen, Space.None); // (
+ // try renderToken(ais, tree, enum_token, Space.None); // enum
+
+ // if (enum_tag_type) |expr| {
+ // try renderToken(ais, tree, tree.nextToken(enum_token), Space.None); // (
+ // try renderExpression(allocator, ais, tree, expr, Space.None);
+
+ // const rparen = tree.nextToken(expr.lastToken());
+ // try renderToken(ais, tree, rparen, Space.None); // )
+ // try renderToken(ais, tree, tree.nextToken(rparen), Space.Space); // )
+ // } else {
+ // try renderToken(ais, tree, tree.nextToken(enum_token), Space.Space); // )
+ // }
+ // },
+ // .Type => |type_expr| {
+ // try renderToken(ais, tree, container_decl.kind_token, Space.None); // union
+
+ // const lparen = tree.nextToken(container_decl.kind_token);
+ // const rparen = tree.nextToken(type_expr.lastToken());
+
+ // try renderToken(ais, tree, lparen, Space.None); // (
+ // try renderExpression(allocator, ais, tree, type_expr, Space.None);
+ // try renderToken(ais, tree, rparen, Space.Space); // )
+ // },
+ // }
+
+ // if (container_decl.fields_and_decls_len == 0) {
+ // {
+ // ais.pushIndentNextLine();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, container_decl.lbrace_token, Space.None); // {
+ // }
+ // return renderToken(ais, tree, container_decl.rbrace_token, space); // }
+ // }
+
+ // const src_has_trailing_comma = blk: {
+ // var maybe_comma = tree.prevToken(container_decl.lastToken());
+ // // Doc comments for a field may also appear after the comma, eg.
+ // // field_name: T, // comment attached to field_name
+ // if (tree.token_tags[maybe_comma] == .DocComment)
+ // maybe_comma = tree.prevToken(maybe_comma);
+ // break :blk tree.token_tags[maybe_comma] == .Comma;
+ // };
+
+ // const fields_and_decls = container_decl.fieldsAndDecls();
+
+ // // Check if the first declaration and the { are on the same line
+ // const src_has_newline = !tree.tokensOnSameLine(
+ // container_decl.lbrace_token,
+ // fields_and_decls[0].firstToken(),
+ // );
+
+ // // We can only print all the elements in-line if all the
+ // // declarations inside are fields
+ // const src_has_only_fields = blk: {
+ // for (fields_and_decls) |decl| {
+ // if (decl.tag != .ContainerField) break :blk false;
+ // }
+ // break :blk true;
+ // };
+
+ // if (src_has_trailing_comma or !src_has_only_fields) {
+ // // One declaration per line
+ // ais.pushIndentNextLine();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, container_decl.lbrace_token, .Newline); // {
+
+ // for (fields_and_decls) |decl, i| {
+ // try renderContainerDecl(allocator, ais, tree, decl, .Newline);
+
+ // if (i + 1 < fields_and_decls.len) {
+ // try renderExtraNewline(tree, ais, fields_and_decls[i + 1]);
+ // }
+ // }
+ // } else if (src_has_newline) {
+ // // All the declarations on the same line, but place the items on
+ // // their own line
+ // try renderToken(ais, tree, container_decl.lbrace_token, .Newline); // {
+
+ // ais.pushIndent();
+ // defer ais.popIndent();
+
+ // for (fields_and_decls) |decl, i| {
+ // const space_after_decl: Space = if (i + 1 >= fields_and_decls.len) .Newline else .Space;
+ // try renderContainerDecl(allocator, ais, tree, decl, space_after_decl);
+ // }
+ // } else {
+ // // All the declarations on the same line
+ // try renderToken(ais, tree, container_decl.lbrace_token, .Space); // {
+
+ // for (fields_and_decls) |decl| {
+ // try renderContainerDecl(allocator, ais, tree, decl, .Space);
+ // }
+ // }
+
+ // return renderToken(ais, tree, container_decl.rbrace_token, space); // }
+ //},
+
+ //.ErrorSetDecl => {
+ // const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
+
+ // const lbrace = tree.nextToken(err_set_decl.error_token);
+
+ // if (err_set_decl.decls_len == 0) {
+ // try renderToken(ais, tree, err_set_decl.error_token, Space.None);
+ // try renderToken(ais, tree, lbrace, Space.None);
+ // return renderToken(ais, tree, err_set_decl.rbrace_token, space);
+ // }
+
+ // if (err_set_decl.decls_len == 1) blk: {
+ // const node = err_set_decl.decls()[0];
+
+ // // if there are any doc comments or same line comments
+ // // don't try to put it all on one line
+ // if (node.cast(ast.Node.ErrorTag)) |tag| {
+ // if (tag.doc_comments != null) break :blk;
+ // } else {
+ // break :blk;
+ // }
+
+ // try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
+ // try renderToken(ais, tree, lbrace, Space.None); // {
+ // try renderExpression(allocator, ais, tree, node, Space.None);
+ // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // }
+ // }
+
+ // try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
+
+ // const src_has_trailing_comma = blk: {
+ // const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
+ // break :blk tree.token_tags[maybe_comma] == .Comma;
+ // };
+
+ // if (src_has_trailing_comma) {
+ // {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+
+ // try renderToken(ais, tree, lbrace, Space.Newline); // {
+ // const decls = err_set_decl.decls();
+ // for (decls) |node, i| {
+ // if (i + 1 < decls.len) {
+ // try renderExpression(allocator, ais, tree, node, Space.None);
+ // try renderToken(ais, tree, tree.nextToken(node.lastToken()), Space.Newline); // ,
+
+ // try renderExtraNewline(tree, ais, decls[i + 1]);
+ // } else {
+ // try renderExpression(allocator, ais, tree, node, Space.Comma);
+ // }
+ // }
+ // }
+
+ // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // }
+ // } else {
+ // try renderToken(ais, tree, lbrace, Space.Space); // {
+
+ // const decls = err_set_decl.decls();
+ // for (decls) |node, i| {
+ // if (i + 1 < decls.len) {
+ // try renderExpression(allocator, ais, tree, node, Space.None);
+
+ // const comma_token = tree.nextToken(node.lastToken());
+ // assert(tree.token_tags[comma_token] == .Comma);
+ // try renderToken(ais, tree, comma_token, Space.Space); // ,
+ // try renderExtraNewline(tree, ais, decls[i + 1]);
+ // } else {
+ // try renderExpression(allocator, ais, tree, node, Space.Space);
+ // }
+ // }
+
+ // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // }
+ // }
+ //},
+
+ //.ErrorTag => {
+ // const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
+
+ // try renderDocComments(tree, ais, tag, tag.doc_comments);
+ // return renderToken(ais, tree, tag.name_token, space); // name
+ //},
+
+ //.MultilineStringLiteral => {
+ // const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
+
+ // {
+ // const locked_indents = ais.lockOneShotIndent();
+ // defer {
+ // var i: u8 = 0;
+ // while (i < locked_indents) : (i += 1) ais.popIndent();
+ // }
+ // try ais.maybeInsertNewline();
+
+ // for (multiline_str_literal.lines()) |t| try renderToken(ais, tree, t, Space.None);
+ // }
+ //},
+
+ //.BuiltinCall => {
+ // const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
+
+ // // TODO remove after 0.7.0 release
+ // if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
+ // return ais.writer().writeAll("opaque {}");
+
+ // // TODO remove after 0.7.0 release
+ // {
+ // const params = builtin_call.paramsConst();
+ // if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
+ // params.len == 1)
+ // {
+ // if (params[0].castTag(.EnumLiteral)) |enum_literal|
+ // if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
+ // return ais.writer().writeAll("opaque {}");
+ // }
+ // }
+
+ // try renderToken(ais, tree, builtin_call.builtin_token, Space.None); // @name
+
+ // const src_params_trailing_comma = blk: {
+ // if (builtin_call.params_len == 0) break :blk false;
+ // const last_node = builtin_call.params()[builtin_call.params_len - 1];
+ // const maybe_comma = tree.nextToken(last_node.lastToken());
+ // break :blk tree.token_tags[maybe_comma] == .Comma;
+ // };
+
+ // const lparen = tree.nextToken(builtin_call.builtin_token);
+
+ // if (!src_params_trailing_comma) {
+ // try renderToken(ais, tree, lparen, Space.None); // (
+
+ // // render all on one line, no trailing comma
+ // const params = builtin_call.params();
+ // for (params) |param_node, i| {
+ // const maybe_comment = param_node.firstToken() - 1;
+ // if (param_node.*.tag == .MultilineStringLiteral or tree.token_tags[maybe_comment] == .LineComment) {
+ // ais.pushIndentOneShot();
+ // }
+ // try renderExpression(allocator, ais, tree, param_node, Space.None);
+
+ // if (i + 1 < params.len) {
+ // const comma_token = tree.nextToken(param_node.lastToken());
+ // try renderToken(ais, tree, comma_token, Space.Space); // ,
+ // }
+ // }
+ // } else {
+ // // one param per line
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, lparen, Space.Newline); // (
+
+ // for (builtin_call.params()) |param_node| {
+ // try renderExpression(allocator, ais, tree, param_node, Space.Comma);
+ // }
+ // }
+
+ // return renderToken(ais, tree, builtin_call.rparen_token, space); // )
+ //},
+
+ //.FnProto => {
+ // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base);
+
+ // if (fn_proto.getVisibToken()) |visib_token_index| {
+ // const visib_token = tree.token_tags[visib_token_index];
+ // assert(visib_token == .Keyword_pub or visib_token == .Keyword_export);
+
+ // try renderToken(ais, tree, visib_token_index, Space.Space); // pub
+ // }
+
+ // if (fn_proto.getExternExportInlineToken()) |extern_export_inline_token| {
+ // if (fn_proto.getIsExternPrototype() == null)
+ // try renderToken(ais, tree, extern_export_inline_token, Space.Space); // extern/export/inline
+ // }
+
+ // if (fn_proto.getLibName()) |lib_name| {
+ // try renderExpression(allocator, ais, tree, lib_name, Space.Space);
+ // }
+
+ // const lparen = if (fn_proto.getNameToken()) |name_token| blk: {
+ // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn
+ // try renderToken(ais, tree, name_token, Space.None); // name
+ // break :blk tree.nextToken(name_token);
+ // } else blk: {
+ // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn
+ // break :blk tree.nextToken(fn_proto.fn_token);
+ // };
+ // assert(tree.token_tags[lparen] == .LParen);
+
+ // const rparen = tree.prevToken(
+ // // the first token for the annotation expressions is the left
+ // // parenthesis, hence the need for two prevToken
+ // if (fn_proto.getAlignExpr()) |align_expr|
+ // tree.prevToken(tree.prevToken(align_expr.firstToken()))
+ // else if (fn_proto.getSectionExpr()) |section_expr|
+ // tree.prevToken(tree.prevToken(section_expr.firstToken()))
+ // else if (fn_proto.getCallconvExpr()) |callconv_expr|
+ // tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
+ // else switch (fn_proto.return_type) {
+ // .Explicit => |node| node.firstToken(),
+ // .InferErrorSet => |node| tree.prevToken(node.firstToken()),
+ // .Invalid => unreachable,
+ // },
+ // );
+ // assert(tree.token_tags[rparen] == .RParen);
+
+ // const src_params_trailing_comma = blk: {
+ // const maybe_comma = tree.token_tags[rparen - 1];
+ // break :blk maybe_comma == .Comma or maybe_comma == .LineComment;
+ // };
+
+ // if (!src_params_trailing_comma) {
+ // try renderToken(ais, tree, lparen, Space.None); // (
+
+ // // render all on one line, no trailing comma
+ // for (fn_proto.params()) |param_decl, i| {
+ // try renderParamDecl(allocator, ais, tree, param_decl, Space.None);
+
+ // if (i + 1 < fn_proto.params_len or fn_proto.getVarArgsToken() != null) {
+ // const comma = tree.nextToken(param_decl.lastToken());
+ // try renderToken(ais, tree, comma, Space.Space); // ,
+ // }
+ // }
+ // if (fn_proto.getVarArgsToken()) |var_args_token| {
+ // try renderToken(ais, tree, var_args_token, Space.None);
+ // }
+ // } else {
+ // // one param per line
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, lparen, Space.Newline); // (
+
+ // for (fn_proto.params()) |param_decl| {
+ // try renderParamDecl(allocator, ais, tree, param_decl, Space.Comma);
+ // }
+ // if (fn_proto.getVarArgsToken()) |var_args_token| {
+ // try renderToken(ais, tree, var_args_token, Space.Comma);
+ // }
+ // }
+
+ // try renderToken(ais, tree, rparen, Space.Space); // )
+
+ // if (fn_proto.getAlignExpr()) |align_expr| {
+ // const align_rparen = tree.nextToken(align_expr.lastToken());
+ // const align_lparen = tree.prevToken(align_expr.firstToken());
+ // const align_kw = tree.prevToken(align_lparen);
+
+ // try renderToken(ais, tree, align_kw, Space.None); // align
+ // try renderToken(ais, tree, align_lparen, Space.None); // (
+ // try renderExpression(allocator, ais, tree, align_expr, Space.None);
+ // try renderToken(ais, tree, align_rparen, Space.Space); // )
+ // }
+
+ // if (fn_proto.getSectionExpr()) |section_expr| {
+ // const section_rparen = tree.nextToken(section_expr.lastToken());
+ // const section_lparen = tree.prevToken(section_expr.firstToken());
+ // const section_kw = tree.prevToken(section_lparen);
+
+ // try renderToken(ais, tree, section_kw, Space.None); // section
+ // try renderToken(ais, tree, section_lparen, Space.None); // (
+ // try renderExpression(allocator, ais, tree, section_expr, Space.None);
+ // try renderToken(ais, tree, section_rparen, Space.Space); // )
+ // }
+
+ // if (fn_proto.getCallconvExpr()) |callconv_expr| {
+ // const callconv_rparen = tree.nextToken(callconv_expr.lastToken());
+ // const callconv_lparen = tree.prevToken(callconv_expr.firstToken());
+ // const callconv_kw = tree.prevToken(callconv_lparen);
+
+ // try renderToken(ais, tree, callconv_kw, Space.None); // callconv
+ // try renderToken(ais, tree, callconv_lparen, Space.None); // (
+ // try renderExpression(allocator, ais, tree, callconv_expr, Space.None);
+ // try renderToken(ais, tree, callconv_rparen, Space.Space); // )
+ // } else if (fn_proto.getIsExternPrototype() != null) {
+ // try ais.writer().writeAll("callconv(.C) ");
+ // } else if (fn_proto.getIsAsync() != null) {
+ // try ais.writer().writeAll("callconv(.Async) ");
+ // }
+
+ // switch (fn_proto.return_type) {
+ // .Explicit => |node| {
+ // return renderExpression(allocator, ais, tree, node, space);
+ // },
+ // .InferErrorSet => |node| {
+ // try renderToken(ais, tree, tree.prevToken(node.firstToken()), Space.None); // !
+ // return renderExpression(allocator, ais, tree, node, space);
+ // },
+ // .Invalid => unreachable,
+ // }
+ //},
+
+ //.AnyFrameType => {
+ // const anyframe_type = @fieldParentPtr(ast.Node.AnyFrameType, "base", base);
+
+ // if (anyframe_type.result) |result| {
+ // try renderToken(ais, tree, anyframe_type.anyframe_token, Space.None); // anyframe
+ // try renderToken(ais, tree, result.arrow_token, Space.None); // ->
+ // return renderExpression(allocator, ais, tree, result.return_type, space);
+ // } else {
+ // return renderToken(ais, tree, anyframe_type.anyframe_token, space); // anyframe
+ // }
+ //},
+
+ //.DocComment => unreachable, // doc comments are attached to nodes
+
+ //.Switch => {
+ // const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
+
+ // try renderToken(ais, tree, switch_node.switch_token, Space.Space); // switch
+ // try renderToken(ais, tree, tree.nextToken(switch_node.switch_token), Space.None); // (
+
+ // const rparen = tree.nextToken(switch_node.expr.lastToken());
+ // const lbrace = tree.nextToken(rparen);
+
+ // if (switch_node.cases_len == 0) {
+ // try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
+ // try renderToken(ais, tree, rparen, Space.Space); // )
+ // try renderToken(ais, tree, lbrace, Space.None); // {
+ // return renderToken(ais, tree, switch_node.rbrace, space); // }
+ // }
+
+ // try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
+ // try renderToken(ais, tree, rparen, Space.Space); // )
+
+ // {
+ // ais.pushIndentNextLine();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, lbrace, Space.Newline); // {
+
+ // const cases = switch_node.cases();
+ // for (cases) |node, i| {
+ // try renderExpression(allocator, ais, tree, node, Space.Comma);
+
+ // if (i + 1 < cases.len) {
+ // try renderExtraNewline(tree, ais, cases[i + 1]);
+ // }
+ // }
+ // }
+
+ // return renderToken(ais, tree, switch_node.rbrace, space); // }
+ //},
+
+ //.SwitchCase => {
+ // const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
+
+ // assert(switch_case.items_len != 0);
+ // const src_has_trailing_comma = blk: {
+ // const last_node = switch_case.items()[switch_case.items_len - 1];
+ // const maybe_comma = tree.nextToken(last_node.lastToken());
+ // break :blk tree.token_tags[maybe_comma] == .Comma;
+ // };
+
+ // if (switch_case.items_len == 1 or !src_has_trailing_comma) {
+ // const items = switch_case.items();
+ // for (items) |node, i| {
+ // if (i + 1 < items.len) {
+ // try renderExpression(allocator, ais, tree, node, Space.None);
+
+ // const comma_token = tree.nextToken(node.lastToken());
+ // try renderToken(ais, tree, comma_token, Space.Space); // ,
+ // try renderExtraNewline(tree, ais, items[i + 1]);
+ // } else {
+ // try renderExpression(allocator, ais, tree, node, Space.Space);
+ // }
+ // }
+ // } else {
+ // const items = switch_case.items();
+ // for (items) |node, i| {
+ // if (i + 1 < items.len) {
+ // try renderExpression(allocator, ais, tree, node, Space.None);
+
+ // const comma_token = tree.nextToken(node.lastToken());
+ // try renderToken(ais, tree, comma_token, Space.Newline); // ,
+ // try renderExtraNewline(tree, ais, items[i + 1]);
+ // } else {
+ // try renderExpression(allocator, ais, tree, node, Space.Comma);
+ // }
+ // }
+ // }
+
+ // try renderToken(ais, tree, switch_case.arrow_token, Space.Space); // =>
+
+ // if (switch_case.payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Space);
+ // }
+
+ // return renderExpression(allocator, ais, tree, switch_case.expr, space);
+ //},
+ //.SwitchElse => {
+ // const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
+ // return renderToken(ais, tree, switch_else.token, space);
+ //},
+ //.Else => {
+ // const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
+
+ // const body_is_block = nodeIsBlock(else_node.body);
+ // const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
+
+ // const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
+ // try renderToken(ais, tree, else_node.else_token, after_else_space);
+
+ // if (else_node.payload) |payload| {
+ // const payload_space = if (same_line) Space.Space else Space.Newline;
+ // try renderExpression(allocator, ais, tree, payload, payload_space);
+ // }
+
+ // if (same_line) {
+ // return renderExpression(allocator, ais, tree, else_node.body, space);
+ // } else {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // return renderExpression(allocator, ais, tree, else_node.body, space);
+ // }
+ //},
+
+ //.While => {
+ // const while_node = @fieldParentPtr(ast.Node.While, "base", base);
+
+ // if (while_node.label) |label| {
+ // try renderToken(ais, tree, label, Space.None); // label
+ // try renderToken(ais, tree, tree.nextToken(label), Space.Space); // :
+ // }
+
+ // if (while_node.inline_token) |inline_token| {
+ // try renderToken(ais, tree, inline_token, Space.Space); // inline
+ // }
+
+ // try renderToken(ais, tree, while_node.while_token, Space.Space); // while
+ // try renderToken(ais, tree, tree.nextToken(while_node.while_token), Space.None); // (
+ // try renderExpression(allocator, ais, tree, while_node.condition, Space.None);
+
+ // const cond_rparen = tree.nextToken(while_node.condition.lastToken());
+
+ // const body_is_block = nodeIsBlock(while_node.body);
+
+ // var block_start_space: Space = undefined;
+ // var after_body_space: Space = undefined;
+
+ // if (body_is_block) {
+ // block_start_space = Space.BlockStart;
+ // after_body_space = if (while_node.@"else" == null) space else Space.SpaceOrOutdent;
+ // } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
+ // block_start_space = Space.Space;
+ // after_body_space = if (while_node.@"else" == null) space else Space.Space;
+ // } else {
+ // block_start_space = Space.Newline;
+ // after_body_space = if (while_node.@"else" == null) space else Space.Newline;
+ // }
+
+ // {
+ // const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
+ // try renderToken(ais, tree, cond_rparen, rparen_space); // )
+ // }
+
+ // if (while_node.payload) |payload| {
+ // const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
+ // try renderExpression(allocator, ais, tree, payload, payload_space);
+ // }
+
+ // if (while_node.continue_expr) |continue_expr| {
+ // const rparen = tree.nextToken(continue_expr.lastToken());
+ // const lparen = tree.prevToken(continue_expr.firstToken());
+ // const colon = tree.prevToken(lparen);
+
+ // try renderToken(ais, tree, colon, Space.Space); // :
+ // try renderToken(ais, tree, lparen, Space.None); // (
+
+ // try renderExpression(allocator, ais, tree, continue_expr, Space.None);
+
+ // try renderToken(ais, tree, rparen, block_start_space); // )
+ // }
+
+ // {
+ // if (!body_is_block) ais.pushIndent();
+ // defer if (!body_is_block) ais.popIndent();
+ // try renderExpression(allocator, ais, tree, while_node.body, after_body_space);
+ // }
+
+ // if (while_node.@"else") |@"else"| {
+ // return renderExpression(allocator, ais, tree, &@"else".base, space);
+ // }
+ //},
+
+ //.For => {
+ // const for_node = @fieldParentPtr(ast.Node.For, "base", base);
+
+ // if (for_node.label) |label| {
+ // try renderToken(ais, tree, label, Space.None); // label
+ // try renderToken(ais, tree, tree.nextToken(label), Space.Space); // :
+ // }
+
+ // if (for_node.inline_token) |inline_token| {
+ // try renderToken(ais, tree, inline_token, Space.Space); // inline
+ // }
+
+ // try renderToken(ais, tree, for_node.for_token, Space.Space); // for
+ // try renderToken(ais, tree, tree.nextToken(for_node.for_token), Space.None); // (
+ // try renderExpression(allocator, ais, tree, for_node.array_expr, Space.None);
+
+ // const rparen = tree.nextToken(for_node.array_expr.lastToken());
+
+ // const body_is_block = for_node.body.tag.isBlock();
+ // const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());
+ // const body_on_same_line = body_is_block or src_one_line_to_body;
+
+ // try renderToken(ais, tree, rparen, Space.Space); // )
+
+ // const space_after_payload = if (body_on_same_line) Space.Space else Space.Newline;
+ // try renderExpression(allocator, ais, tree, for_node.payload, space_after_payload); // |x|
+
+ // const space_after_body = blk: {
+ // if (for_node.@"else") |@"else"| {
+ // const src_one_line_to_else = tree.tokensOnSameLine(rparen, @"else".firstToken());
+ // if (body_is_block or src_one_line_to_else) {
+ // break :blk Space.Space;
+ // } else {
+ // break :blk Space.Newline;
+ // }
+ // } else {
+ // break :blk space;
+ // }
+ // };
+
+ // {
+ // if (!body_on_same_line) ais.pushIndent();
+ // defer if (!body_on_same_line) ais.popIndent();
+ // try renderExpression(allocator, ais, tree, for_node.body, space_after_body); // { body }
+ // }
+
+ // if (for_node.@"else") |@"else"| {
+ // return renderExpression(allocator, ais, tree, &@"else".base, space); // else
+ // }
+ //},
+
+ //.If => {
+ // const if_node = @fieldParentPtr(ast.Node.If, "base", base);
+
+ // const lparen = tree.nextToken(if_node.if_token);
+ // const rparen = tree.nextToken(if_node.condition.lastToken());
+
+ // try renderToken(ais, tree, if_node.if_token, Space.Space); // if
+ // try renderToken(ais, tree, lparen, Space.None); // (
+
+ // try renderExpression(allocator, ais, tree, if_node.condition, Space.None); // condition
+
+ // const body_is_if_block = if_node.body.tag == .If;
+ // const body_is_block = nodeIsBlock(if_node.body);
+
+ // if (body_is_if_block) {
+ // try renderExtraNewline(tree, ais, if_node.body);
+ // } else if (body_is_block) {
+ // const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
+ // try renderToken(ais, tree, rparen, after_rparen_space); // )
+
+ // if (if_node.payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.BlockStart); // |x|
+ // }
+
+ // if (if_node.@"else") |@"else"| {
+ // try renderExpression(allocator, ais, tree, if_node.body, Space.SpaceOrOutdent);
+ // return renderExpression(allocator, ais, tree, &@"else".base, space);
+ // } else {
+ // return renderExpression(allocator, ais, tree, if_node.body, space);
+ // }
+ // }
+
+ // const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken());
+
+ // if (src_has_newline) {
+ // const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space;
+
+ // {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // try renderToken(ais, tree, rparen, after_rparen_space); // )
+ // }
+
+ // if (if_node.payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Newline);
+ // }
+
+ // if (if_node.@"else") |@"else"| {
+ // const else_is_block = nodeIsBlock(@"else".body);
+
+ // {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // try renderExpression(allocator, ais, tree, if_node.body, Space.Newline);
+ // }
+
+ // if (else_is_block) {
+ // try renderToken(ais, tree, @"else".else_token, Space.Space); // else
+
+ // if (@"else".payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Space);
+ // }
+
+ // return renderExpression(allocator, ais, tree, @"else".body, space);
+ // } else {
+ // const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;
+ // try renderToken(ais, tree, @"else".else_token, after_else_space); // else
+
+ // if (@"else".payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Newline);
+ // }
+
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // return renderExpression(allocator, ais, tree, @"else".body, space);
+ // }
+ // } else {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // return renderExpression(allocator, ais, tree, if_node.body, space);
+ // }
+ // }
+
+ // // Single line if statement
+
+ // try renderToken(ais, tree, rparen, Space.Space); // )
+
+ // if (if_node.payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Space);
+ // }
+
+ // if (if_node.@"else") |@"else"| {
+ // try renderExpression(allocator, ais, tree, if_node.body, Space.Space);
+ // try renderToken(ais, tree, @"else".else_token, Space.Space);
+
+ // if (@"else".payload) |payload| {
+ // try renderExpression(allocator, ais, tree, payload, Space.Space);
+ // }
+
+ // return renderExpression(allocator, ais, tree, @"else".body, space);
+ // } else {
+ // return renderExpression(allocator, ais, tree, if_node.body, space);
+ // }
+ //},
+
+ //.Asm => {
+ // const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
+
+ // try renderToken(ais, tree, asm_node.asm_token, Space.Space); // asm
+
+ // if (asm_node.volatile_token) |volatile_token| {
+ // try renderToken(ais, tree, volatile_token, Space.Space); // volatile
+ // try renderToken(ais, tree, tree.nextToken(volatile_token), Space.None); // (
+ // } else {
+ // try renderToken(ais, tree, tree.nextToken(asm_node.asm_token), Space.None); // (
+ // }
+
+ // asmblk: {
+ // ais.pushIndent();
+ // defer ais.popIndent();
+
+ // if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
+ // try renderExpression(allocator, ais, tree, asm_node.template, Space.None);
+ // break :asmblk;
+ // }
+
+ // try renderExpression(allocator, ais, tree, asm_node.template, Space.Newline);
+
+ // ais.setIndentDelta(asm_indent_delta);
+ // defer ais.setIndentDelta(indent_delta);
+
+ // const colon1 = tree.nextToken(asm_node.template.lastToken());
+
+ // const colon2 = if (asm_node.outputs.len == 0) blk: {
+ // try renderToken(ais, tree, colon1, Space.Newline); // :
+
+ // break :blk tree.nextToken(colon1);
+ // } else blk: {
+ // try renderToken(ais, tree, colon1, Space.Space); // :
+
+ // ais.pushIndent();
+ // defer ais.popIndent();
+
+ // for (asm_node.outputs) |*asm_output, i| {
+ // if (i + 1 < asm_node.outputs.len) {
+ // const next_asm_output = asm_node.outputs[i + 1];
+ // try renderAsmOutput(allocator, ais, tree, asm_output, Space.None);
+
+ // const comma = tree.prevToken(next_asm_output.firstToken());
+ // try renderToken(ais, tree, comma, Space.Newline); // ,
+ // try renderExtraNewlineToken(tree, ais, next_asm_output.firstToken());
+ // } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
+ // try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
+ // break :asmblk;
+ // } else {
+ // try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
+ // const comma_or_colon = tree.nextToken(asm_output.lastToken());
+ // break :blk switch (tree.token_tags[comma_or_colon]) {
+ // .Comma => tree.nextToken(comma_or_colon),
+ // else => comma_or_colon,
+ // };
+ // }
+ // }
+ // unreachable;
+ // };
+
+ // const colon3 = if (asm_node.inputs.len == 0) blk: {
+ // try renderToken(ais, tree, colon2, Space.Newline); // :
+ // break :blk tree.nextToken(colon2);
+ // } else blk: {
+ // try renderToken(ais, tree, colon2, Space.Space); // :
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // for (asm_node.inputs) |*asm_input, i| {
+ // if (i + 1 < asm_node.inputs.len) {
+ // const next_asm_input = &asm_node.inputs[i + 1];
+ // try renderAsmInput(allocator, ais, tree, asm_input, Space.None);
+
+ // const comma = tree.prevToken(next_asm_input.firstToken());
+ // try renderToken(ais, tree, comma, Space.Newline); // ,
+ // try renderExtraNewlineToken(tree, ais, next_asm_input.firstToken());
+ // } else if (asm_node.clobbers.len == 0) {
+ // try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
+ // break :asmblk;
+ // } else {
+ // try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
+ // const comma_or_colon = tree.nextToken(asm_input.lastToken());
+ // break :blk switch (tree.token_tags[comma_or_colon]) {
+ // .Comma => tree.nextToken(comma_or_colon),
+ // else => comma_or_colon,
+ // };
+ // }
+ // }
+ // unreachable;
+ // };
+
+ // try renderToken(ais, tree, colon3, Space.Space); // :
+ // ais.pushIndent();
+ // defer ais.popIndent();
+ // for (asm_node.clobbers) |clobber_node, i| {
+ // if (i + 1 >= asm_node.clobbers.len) {
+ // try renderExpression(allocator, ais, tree, clobber_node, Space.Newline);
+ // break :asmblk;
+ // } else {
+ // try renderExpression(allocator, ais, tree, clobber_node, Space.None);
+ // const comma = tree.nextToken(clobber_node.lastToken());
+ // try renderToken(ais, tree, comma, Space.Space); // ,
+ // }
+ // }
+ // }
+
+ // return renderToken(ais, tree, asm_node.rparen, space);
+ //},
+
+ //.EnumLiteral => {
+ // const enum_literal = @fieldParentPtr(ast.Node.EnumLiteral, "base", base);
+
+ // try renderToken(ais, tree, enum_literal.dot, Space.None); // .
+ // return renderToken(ais, tree, enum_literal.name, space); // name
+ //},
+
+ //.ContainerField,
+ //.Root,
+ //.VarDecl,
+ //.Use,
+ //.TestDecl,
+ //=> unreachable,
+ else => @panic("TODO implement more renderExpression"),
}
}
fn renderArrayType(
allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
+ ais: *Ais,
+ tree: ast.Tree,
lbracket: ast.TokenIndex,
- rhs: *ast.Node,
- len_expr: *ast.Node,
- opt_sentinel: ?*ast.Node,
+ rhs: ast.Node.Index,
+ len_expr: ast.Node.Index,
+ opt_sentinel: ?ast.Node.Index,
space: Space,
-) (@TypeOf(ais.*).Error || Error)!void {
+) Error!void {
const rbracket = tree.nextToken(if (opt_sentinel) |sentinel|
sentinel.lastToken()
else
len_expr.lastToken());
- const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment;
- const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment;
+ const starts_with_comment = tree.token_tags[lbracket + 1] == .LineComment;
+ const ends_with_comment = tree.token_tags[rbracket - 1] == .LineComment;
const new_space = if (ends_with_comment) Space.Newline else Space.None;
{
const do_indent = (starts_with_comment or ends_with_comment);
if (do_indent) ais.pushIndent();
defer if (do_indent) ais.popIndent();
- try renderToken(tree, ais, lbracket, Space.None); // [
+ try renderToken(ais, tree, lbracket, Space.None); // [
try renderExpression(allocator, ais, tree, len_expr, new_space);
if (starts_with_comment) {
@@ -2182,25 +2087,25 @@ fn renderArrayType(
}
if (opt_sentinel) |sentinel| {
const colon_token = tree.prevToken(sentinel.firstToken());
- try renderToken(tree, ais, colon_token, Space.None); // :
+ try renderToken(ais, tree, colon_token, Space.None); // :
try renderExpression(allocator, ais, tree, sentinel, Space.None);
}
if (starts_with_comment) {
try ais.maybeInsertNewline();
}
}
- try renderToken(tree, ais, rbracket, Space.None); // ]
+ try renderToken(ais, tree, rbracket, Space.None); // ]
return renderExpression(allocator, ais, tree, rhs, space);
}
fn renderAsmOutput(
allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
+ ais: *Ais,
+ tree: ast.Tree,
asm_output: *const ast.Node.Asm.Output,
space: Space,
-) (@TypeOf(ais.*).Error || Error)!void {
+) Error!void {
try ais.writer().writeAll("[");
try renderExpression(allocator, ais, tree, asm_output.symbolic_name, Space.None);
try ais.writer().writeAll("] ");
@@ -2217,37 +2122,37 @@ fn renderAsmOutput(
},
}
- return renderToken(tree, ais, asm_output.lastToken(), space); // )
+ return renderToken(ais, tree, asm_output.lastToken(), space); // )
}
fn renderAsmInput(
allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
+ ais: *Ais,
+ tree: ast.Tree,
asm_input: *const ast.Node.Asm.Input,
space: Space,
-) (@TypeOf(ais.*).Error || Error)!void {
+) Error!void {
try ais.writer().writeAll("[");
try renderExpression(allocator, ais, tree, asm_input.symbolic_name, Space.None);
try ais.writer().writeAll("] ");
try renderExpression(allocator, ais, tree, asm_input.constraint, Space.None);
try ais.writer().writeAll(" (");
try renderExpression(allocator, ais, tree, asm_input.expr, Space.None);
- return renderToken(tree, ais, asm_input.lastToken(), space); // )
+ return renderToken(ais, tree, asm_input.lastToken(), space); // )
}
fn renderVarDecl(
allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
- var_decl: *ast.Node.VarDecl,
-) (@TypeOf(ais.*).Error || Error)!void {
+ ais: *Ais,
+ tree: ast.Tree,
+ var_decl: ast.Node.Index.VarDecl,
+) Error!void {
if (var_decl.getVisibToken()) |visib_token| {
- try renderToken(tree, ais, visib_token, Space.Space); // pub
+ try renderToken(ais, tree, visib_token, Space.Space); // pub
}
if (var_decl.getExternExportToken()) |extern_export_token| {
- try renderToken(tree, ais, extern_export_token, Space.Space); // extern
+ try renderToken(ais, tree, extern_export_token, Space.Space); // extern
if (var_decl.getLibName()) |lib_name| {
try renderExpression(allocator, ais, tree, lib_name, Space.Space); // "lib"
@@ -2255,13 +2160,13 @@ fn renderVarDecl(
}
if (var_decl.getComptimeToken()) |comptime_token| {
- try renderToken(tree, ais, comptime_token, Space.Space); // comptime
+ try renderToken(ais, tree, comptime_token, Space.Space); // comptime
}
if (var_decl.getThreadLocalToken()) |thread_local_token| {
- try renderToken(tree, ais, thread_local_token, Space.Space); // threadlocal
+ try renderToken(ais, tree, thread_local_token, Space.Space); // threadlocal
}
- try renderToken(tree, ais, var_decl.mut_token, Space.Space); // var
+ try renderToken(ais, tree, var_decl.mut_token, Space.Space); // var
const name_space = if (var_decl.getTypeNode() == null and
(var_decl.getAlignNode() != null or
@@ -2270,10 +2175,10 @@ fn renderVarDecl(
Space.Space
else
Space.None;
- try renderToken(tree, ais, var_decl.name_token, name_space);
+ try renderToken(ais, tree, var_decl.name_token, name_space);
if (var_decl.getTypeNode()) |type_node| {
- try renderToken(tree, ais, tree.nextToken(var_decl.name_token), Space.Space);
+ try renderToken(ais, tree, tree.nextToken(var_decl.name_token), Space.Space);
const s = if (var_decl.getAlignNode() != null or
var_decl.getSectionNode() != null or
var_decl.getInitNode() != null) Space.Space else Space.None;
@@ -2284,22 +2189,22 @@ fn renderVarDecl(
const lparen = tree.prevToken(align_node.firstToken());
const align_kw = tree.prevToken(lparen);
const rparen = tree.nextToken(align_node.lastToken());
- try renderToken(tree, ais, align_kw, Space.None); // align
- try renderToken(tree, ais, lparen, Space.None); // (
+ try renderToken(ais, tree, align_kw, Space.None); // align
+ try renderToken(ais, tree, lparen, Space.None); // (
try renderExpression(allocator, ais, tree, align_node, Space.None);
const s = if (var_decl.getSectionNode() != null or var_decl.getInitNode() != null) Space.Space else Space.None;
- try renderToken(tree, ais, rparen, s); // )
+ try renderToken(ais, tree, rparen, s); // )
}
if (var_decl.getSectionNode()) |section_node| {
const lparen = tree.prevToken(section_node.firstToken());
const section_kw = tree.prevToken(lparen);
const rparen = tree.nextToken(section_node.lastToken());
- try renderToken(tree, ais, section_kw, Space.None); // linksection
- try renderToken(tree, ais, lparen, Space.None); // (
+ try renderToken(ais, tree, section_kw, Space.None); // linksection
+ try renderToken(ais, tree, lparen, Space.None); // (
try renderExpression(allocator, ais, tree, section_node, Space.None);
const s = if (var_decl.getInitNode() != null) Space.Space else Space.None;
- try renderToken(tree, ais, rparen, s); // )
+ try renderToken(ais, tree, rparen, s); // )
}
if (var_decl.getInitNode()) |init_node| {
@@ -2312,268 +2217,150 @@ fn renderVarDecl(
{
ais.pushIndent();
defer ais.popIndent();
- try renderToken(tree, ais, eq_token, eq_space); // =
+ try renderToken(ais, tree, eq_token, eq_space); // =
}
ais.pushIndentOneShot();
try renderExpression(allocator, ais, tree, init_node, Space.None);
}
- try renderToken(tree, ais, var_decl.semicolon_token, Space.Newline);
+ try renderToken(ais, tree, var_decl.semicolon_token, Space.Newline);
}
fn renderParamDecl(
allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
+ ais: *Ais,
+ tree: ast.Tree,
param_decl: ast.Node.FnProto.ParamDecl,
space: Space,
-) (@TypeOf(ais.*).Error || Error)!void {
+) Error!void {
try renderDocComments(tree, ais, param_decl, param_decl.doc_comments);
if (param_decl.comptime_token) |comptime_token| {
- try renderToken(tree, ais, comptime_token, Space.Space);
+ try renderToken(ais, tree, comptime_token, Space.Space);
}
if (param_decl.noalias_token) |noalias_token| {
- try renderToken(tree, ais, noalias_token, Space.Space);
+ try renderToken(ais, tree, noalias_token, Space.Space);
}
if (param_decl.name_token) |name_token| {
- try renderToken(tree, ais, name_token, Space.None);
- try renderToken(tree, ais, tree.nextToken(name_token), Space.Space); // :
+ try renderToken(ais, tree, name_token, Space.None);
+ try renderToken(ais, tree, tree.nextToken(name_token), Space.Space); // :
}
switch (param_decl.param_type) {
.any_type, .type_expr => |node| try renderExpression(allocator, ais, tree, node, space),
}
}
-fn renderStatement(
- allocator: *mem.Allocator,
- ais: anytype,
- tree: *ast.Tree,
- base: *ast.Node,
-) (@TypeOf(ais.*).Error || Error)!void {
- switch (base.tag) {
- .VarDecl => {
- const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
- try renderVarDecl(allocator, ais, tree, var_decl);
- },
- else => {
- if (base.requireSemiColon()) {
- try renderExpression(allocator, ais, tree, base, Space.None);
-
- const semicolon_index = tree.nextToken(base.lastToken());
- assert(tree.token_ids[semicolon_index] == .Semicolon);
- try renderToken(tree, ais, semicolon_index, Space.Newline);
- } else {
- try renderExpression(allocator, ais, tree, base, Space.Newline);
- }
- },
- }
+fn renderStatement(ais: *Ais, tree: ast.Tree, base: ast.Node.Index) Error!void {
+ @panic("TODO render statement");
+ //switch (base.tag) {
+ // .VarDecl => {
+ // const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
+ // try renderVarDecl(allocator, ais, tree, var_decl);
+ // },
+ // else => {
+ // if (base.requireSemiColon()) {
+ // try renderExpression(allocator, ais, tree, base, Space.None);
+
+ // const semicolon_index = tree.nextToken(base.lastToken());
+ // assert(tree.token_tags[semicolon_index] == .Semicolon);
+ // try renderToken(ais, tree, semicolon_index, Space.Newline);
+ // } else {
+ // try renderExpression(allocator, ais, tree, base, Space.Newline);
+ // }
+ // },
+ //}
}
const Space = enum {
None,
Newline,
+ /// `renderToken` will additionally consume the next token if it is a comma.
Comma,
Space,
SpaceOrOutdent,
NoNewline,
+ /// Skips writing the possible line comment after the token.
NoComment,
BlockStart,
};
-fn renderTokenOffset(
- tree: *ast.Tree,
- ais: anytype,
- token_index: ast.TokenIndex,
- space: Space,
- token_skip_bytes: usize,
-) (@TypeOf(ais.*).Error || Error)!void {
+fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Space) Error!void {
if (space == Space.BlockStart) {
- // If placing the lbrace on the current line would cause an uggly gap then put the lbrace on the next line
+ // If placing the lbrace on the current line would cause an ugly gap then put the lbrace on the next line.
const new_space = if (ais.isLineOverIndented()) Space.Newline else Space.Space;
- return renderToken(tree, ais, token_index, new_space);
+ return renderToken(ais, tree, token_index, new_space);
}
- var token_loc = tree.token_locs[token_index];
- try ais.writer().writeAll(mem.trimRight(u8, tree.tokenSliceLoc(token_loc)[token_skip_bytes..], " "));
+ const token_tags = tree.tokens.items(.tag);
+ const token_starts = tree.tokens.items(.start);
- if (space == Space.NoComment)
- return;
+ const token_start = token_starts[token_index];
+ const token_tag = token_tags[token_index];
+ const lexeme = token_tag.lexeme() orelse lexeme: {
+ var tokenizer: std.zig.Tokenizer = .{
+ .buffer = tree.source,
+ .index = token_start,
+ .pending_invalid_token = null,
+ };
+ const token = tokenizer.next();
+ assert(token.tag == token_tag);
+ break :lexeme tree.source[token.loc.start..token.loc.end];
+ };
+ try ais.writer().writeAll(lexeme);
- var next_token_id = tree.token_ids[token_index + 1];
- var next_token_loc = tree.token_locs[token_index + 1];
+ switch (space) {
+ .NoComment => {},
+ .NoNewline => {},
+ .None => {},
+ .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 (space == Space.Comma) switch (next_token_id) {
- .Comma => return renderToken(tree, ais, token_index + 1, Space.Newline),
- .LineComment => {
- try ais.writer().writeAll(", ");
- return renderToken(tree, ais, token_index + 1, Space.Newline);
- },
- else => {
- if (token_index + 2 < tree.token_ids.len and
- tree.token_ids[token_index + 2] == .MultilineStringLiteralLine)
- {
- try ais.writer().writeAll(",");
- return;
- } else {
- try ais.writer().writeAll(",");
+ if (token_tags[token_index + 2] != .MultilineStringLiteralLine) {
try ais.insertNewline();
- return;
}
},
- };
-
- // Skip over same line doc comments
- var offset: usize = 1;
- if (next_token_id == .DocComment) {
- const loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
- if (loc.line == 0) {
- offset += 1;
- next_token_id = tree.token_ids[token_index + offset];
- next_token_loc = tree.token_locs[token_index + offset];
- }
- }
-
- if (next_token_id != .LineComment) {
- switch (space) {
- Space.None, Space.NoNewline => return,
- Space.Newline => {
- if (next_token_id == .MultilineStringLiteralLine) {
- return;
- } else {
- try ais.insertNewline();
- return;
- }
- },
- Space.Space, Space.SpaceOrOutdent => {
- if (next_token_id == .MultilineStringLiteralLine)
- return;
- try ais.writer().writeByte(' ');
- return;
- },
- Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
- }
- }
-
- while (true) {
- const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(next_token_loc), " ").len == 2;
- if (comment_is_empty) {
- switch (space) {
- Space.Newline => {
- offset += 1;
- token_loc = next_token_loc;
- next_token_id = tree.token_ids[token_index + offset];
- next_token_loc = tree.token_locs[token_index + offset];
- if (next_token_id != .LineComment) {
- try ais.insertNewline();
- return;
- }
- },
- else => break,
- }
- } else {
- break;
- }
- }
-
- var loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
- if (loc.line == 0) {
- if (tree.token_ids[token_index] != .MultilineStringLiteralLine) {
+ .SpaceOrOutdent => @panic("what does this even do"),
+ .Space => {
+ _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");
try ais.writer().writeByte(' ');
- }
- try ais.writer().writeAll(mem.trimRight(u8, tree.tokenSliceLoc(next_token_loc), " "));
- offset = 2;
- token_loc = next_token_loc;
- next_token_loc = tree.token_locs[token_index + offset];
- next_token_id = tree.token_ids[token_index + offset];
- if (next_token_id != .LineComment) {
- switch (space) {
- .None, .Space, .SpaceOrOutdent => {
- try ais.insertNewline();
- },
- .Newline => {
- if (next_token_id == .MultilineStringLiteralLine) {
- return;
- } else {
- try ais.insertNewline();
- return;
- }
- },
- .NoNewline => {},
- .NoComment, .Comma, .BlockStart => unreachable,
- }
- return;
- }
- loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
- }
-
- while (true) {
- // translate-c doesn't generate correct newlines
- // in generated code (loc.line == 0) so treat that case
- // as though there was meant to be a newline between the tokens
- var newline_count = if (loc.line <= 1) @as(u8, 1) else @as(u8, 2);
- while (newline_count > 0) : (newline_count -= 1) try ais.insertNewline();
- try ais.writer().writeAll(mem.trimRight(u8, tree.tokenSliceLoc(next_token_loc), " "));
-
- offset += 1;
- token_loc = next_token_loc;
- next_token_loc = tree.token_locs[token_index + offset];
- next_token_id = tree.token_ids[token_index + offset];
- if (next_token_id != .LineComment) {
- switch (space) {
- .Newline => {
- if (next_token_id == .MultilineStringLiteralLine) {
- return;
- } else {
- try ais.insertNewline();
- return;
- }
- },
- .None, .Space, .SpaceOrOutdent => {
- try ais.insertNewline();
- },
- .NoNewline => {},
- .NoComment, .Comma, .BlockStart => unreachable,
+ },
+ .Newline => {
+ if (token_tags[token_index + 1] != .MultilineStringLiteralLine) {
+ try ais.insertNewline();
}
- return;
- }
- loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
+ },
+ .BlockStart => unreachable,
}
}
-fn renderToken(
- tree: *ast.Tree,
- ais: anytype,
- token_index: ast.TokenIndex,
- space: Space,
-) (@TypeOf(ais.*).Error || Error)!void {
- return renderTokenOffset(tree, ais, token_index, space, 0);
-}
-
fn renderDocComments(
- tree: *ast.Tree,
- ais: anytype,
+ tree: ast.Tree,
+ ais: *Ais,
node: anytype,
- doc_comments: ?*ast.Node.DocComment,
-) (@TypeOf(ais.*).Error || Error)!void {
+ doc_comments: ?ast.Node.Index.DocComment,
+) Error!void {
const comment = doc_comments orelse return;
return renderDocCommentsToken(tree, ais, comment, node.firstToken());
}
fn renderDocCommentsToken(
- tree: *ast.Tree,
- ais: anytype,
- comment: *ast.Node.DocComment,
+ tree: ast.Tree,
+ ais: *Ais,
+ comment: ast.Node.Index.DocComment,
first_token: ast.TokenIndex,
-) (@TypeOf(ais.*).Error || Error)!void {
+) Error!void {
var tok_i = comment.first_line;
while (true) : (tok_i += 1) {
- switch (tree.token_ids[tok_i]) {
+ switch (tree.token_tags[tok_i]) {
.DocComment, .ContainerDocComment => {
if (comment.first_line < first_token) {
- try renderToken(tree, ais, tok_i, Space.Newline);
+ try renderToken(ais, tree, tok_i, Space.Newline);
} else {
- try renderToken(tree, ais, tok_i, Space.NoComment);
+ try renderToken(ais, tree, tok_i, Space.NoComment);
try ais.insertNewline();
}
},
@@ -2596,7 +2383,7 @@ fn nodeIsBlock(base: *const ast.Node) bool {
};
}
-fn nodeCausesSliceOpSpace(base: *ast.Node) bool {
+fn nodeCausesSliceOpSpace(base: ast.Node.Index) bool {
return switch (base.tag) {
.Catch,
.Add,
@@ -2646,7 +2433,7 @@ fn nodeCausesSliceOpSpace(base: *ast.Node) bool {
};
}
-fn copyFixingWhitespace(ais: anytype, slice: []const u8) @TypeOf(ais.*).Error!void {
+fn copyFixingWhitespace(ais: *Ais, slice: []const u8) @TypeOf(ais.*).Error!void {
for (slice) |byte| switch (byte) {
'\t' => try ais.writer().writeAll(" "),
'\r' => {},
@@ -2656,12 +2443,12 @@ fn copyFixingWhitespace(ais: anytype, slice: []const u8) @TypeOf(ais.*).Error!vo
// Returns the number of nodes in `expr` that are on the same line as `rtoken`,
// or null if they all are on the same line.
-fn rowSize(tree: *ast.Tree, exprs: []*ast.Node, rtoken: ast.TokenIndex) ?usize {
+fn rowSize(tree: ast.Tree, exprs: []ast.Node.Index, rtoken: ast.TokenIndex) ?usize {
const first_token = exprs[0].firstToken();
const first_loc = tree.tokenLocation(tree.token_locs[first_token].start, rtoken);
if (first_loc.line == 0) {
const maybe_comma = tree.prevToken(rtoken);
- if (tree.token_ids[maybe_comma] == .Comma)
+ if (tree.token_tags[maybe_comma] == .Comma)
return 1;
return null; // no newlines
}
diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig
index 8692713eb3..642c09e477 100644
--- a/lib/std/zig/tokenizer.zig
+++ b/lib/std/zig/tokenizer.zig
@@ -195,22 +195,23 @@ pub const Token = struct {
Keyword_volatile,
Keyword_while,
- pub fn symbol(tag: Tag) []const u8 {
+ pub fn lexeme(tag: Tag) ?[]const u8 {
return switch (tag) {
- .Invalid => "Invalid",
+ .Invalid,
+ .Identifier,
+ .StringLiteral,
+ .MultilineStringLiteralLine,
+ .CharLiteral,
+ .Eof,
+ .Builtin,
+ .IntegerLiteral,
+ .FloatLiteral,
+ .DocComment,
+ .ContainerDocComment,
+ => null,
+
.Invalid_ampersands => "&&",
.Invalid_periodasterisks => ".**",
- .Identifier => "Identifier",
- .StringLiteral => "StringLiteral",
- .MultilineStringLiteralLine => "MultilineStringLiteralLine",
- .CharLiteral => "CharLiteral",
- .Eof => "Eof",
- .Builtin => "Builtin",
- .IntegerLiteral => "IntegerLiteral",
- .FloatLiteral => "FloatLiteral",
- .DocComment => "DocComment",
- .ContainerDocComment => "ContainerDocComment",
-
.Bang => "!",
.Pipe => "|",
.PipePipe => "||",
@@ -319,6 +320,10 @@ pub const Token = struct {
.Keyword_while => "while",
};
}
+
+ pub fn symbol(tag: Tag) []const u8 {
+ return tag.lexeme() orelse @tagName(tag);
+ }
};
};