authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-01 17:23:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-01 17:23:49-07:00
log20554d32c0a9e8adeb311645797e0d6873f4bbc0
tree1080a2c4700156e8b1283ddbadad64e1f4520063
parentbf8fafc37d4182196d108c773ae36c33a109d703

zig fmt: start reworking with new memory layout

* start implementation of ast.Tree.firstToken and lastToken * clarify some ast.Node doc comments * reimplement renderToken

5 files changed, 6134 insertions(+), 6093 deletions(-)

lib/std/zig/ast.zig+285-15
...@@ -185,24 +185,293 @@ pub const Tree = struct {...@@ -185,24 +185,293 @@ pub const Tree = struct {
185 }185 }
186 }186 }
187187
188 /// Skips over comments.188 pub fn firstToken(tree: Tree, node: Node.Index) TokenIndex {
189 pub fn prevToken(self: *const Tree, token_index: TokenIndex) TokenIndex {189 const tags = tree.nodes.items(.tag);
190 const token_tags = self.tokens.items(.tag);190 const datas = tree.nodes.items(.data);
191 var index = token_index - 1;191 const main_tokens = tree.nodes.items(.main_token);
192 while (token_tags[index] == .LineComment) {192 switch (tags[node]) {
193 index -= 1;193 .Root => return 0,
194
195 .UsingNamespace,
196 .TestDecl,
197 .ErrDefer,
198 .Defer,
199 .BoolNot,
200 .Negation,
201 .BitNot,
202 .NegationWrap,
203 .AddressOf,
204 .Try,
205 .Await,
206 .OptionalType,
207 .ArrayInitDotTwo,
208 .ArrayInitDot,
209 .StructInitDotTwo,
210 .StructInitDot,
211 .Switch,
212 .IfSimple,
213 .IfSimpleOptional,
214 .If,
215 .IfOptional,
216 .IfError,
217 .Suspend,
218 .Resume,
219 .Continue,
220 .Break,
221 .Return,
222 .AnyFrameType,
223 .OneToken,
224 .Identifier,
225 .EnumLiteral,
226 .MultilineStringLiteral,
227 .GroupedExpression,
228 .BuiltinCallTwo,
229 .BuiltinCall,
230 .ErrorSetDecl,
231 .AnyType,
232 .Comptime,
233 .Nosuspend,
234 .Block,
235 .AsmSimple,
236 .Asm,
237 => return main_tokens[node],
238
239 .Catch,
240 .FieldAccess,
241 .UnwrapOptional,
242 .EqualEqual,
243 .BangEqual,
244 .LessThan,
245 .GreaterThan,
246 .LessOrEqual,
247 .GreaterOrEqual,
248 .AssignMul,
249 .AssignDiv,
250 .AssignMod,
251 .AssignAdd,
252 .AssignSub,
253 .AssignBitShiftLeft,
254 .AssignBitShiftRight,
255 .AssignBitAnd,
256 .AssignBitXor,
257 .AssignBitOr,
258 .AssignMulWrap,
259 .AssignAddWrap,
260 .AssignSubWrap,
261 .Assign,
262 .MergeErrorSets,
263 .Mul,
264 .Div,
265 .Mod,
266 .ArrayMult,
267 .MulWrap,
268 .Add,
269 .Sub,
270 .ArrayCat,
271 .AddWrap,
272 .SubWrap,
273 .BitShiftLeft,
274 .BitShiftRight,
275 .BitAnd,
276 .BitXor,
277 .BitOr,
278 .OrElse,
279 .BoolAnd,
280 .BoolOr,
281 .SliceOpen,
282 .Slice,
283 .Deref,
284 .ArrayAccess,
285 .ArrayInitOne,
286 .ArrayInit,
287 .StructInitOne,
288 .CallOne,
289 .Call,
290 .SwitchCaseOne,
291 .SwitchRange,
292 .FnDecl,
293 => return tree.firstToken(datas[node].lhs),
294
295 .GlobalVarDecl,
296 .LocalVarDecl,
297 .SimpleVarDecl,
298 .AlignedVarDecl,
299 .ArrayType,
300 .ArrayTypeSentinel,
301 .PtrTypeAligned,
302 .PtrTypeSentinel,
303 .PtrType,
304 .SliceType,
305 .StructInit,
306 .SwitchCaseMulti,
307 .WhileSimple,
308 .WhileSimpleOptional,
309 .WhileCont,
310 .WhileContOptional,
311 .While,
312 .WhileOptional,
313 .WhileError,
314 .ForSimple,
315 .For,
316 .FnProtoSimple,
317 .FnProtoSimpleMulti,
318 .FnProtoOne,
319 .FnProto,
320 .ContainerDecl,
321 .ContainerDeclArg,
322 .TaggedUnion,
323 .TaggedUnionEnumTag,
324 .ContainerFieldInit,
325 .ContainerFieldAlign,
326 .ContainerField,
327 .AsmOutput,
328 .AsmInput,
329 .ErrorValue,
330 .ErrorUnion,
331 => @panic("TODO finish implementing firstToken"),
194 }332 }
195 return index;
196 }333 }
197334
198 /// Skips over comments.335 pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex {
199 pub fn nextToken(self: *const Tree, token_index: TokenIndex) TokenIndex {336 const tags = tree.nodes.items(.tag);
200 const token_tags = self.tokens.items(.tag);337 const datas = tree.nodes.items(.data);
201 var index = token_index + 1;338 const main_tokens = tree.nodes.items(.main_token);
202 while (token_tags[index] == .LineComment) {339 switch (tags[node]) {
203 index += 1;340 .Root,
341 .UsingNamespace,
342 .TestDecl,
343 .ErrDefer,
344 .Defer,
345 .BoolNot,
346 .Negation,
347 .BitNot,
348 .NegationWrap,
349 .AddressOf,
350 .Try,
351 .Await,
352 .OptionalType,
353 .ArrayInitDotTwo,
354 .ArrayInitDot,
355 .StructInitDotTwo,
356 .StructInitDot,
357 .Switch,
358 .IfSimple,
359 .IfSimpleOptional,
360 .If,
361 .IfOptional,
362 .IfError,
363 .Suspend,
364 .Resume,
365 .Continue,
366 .Break,
367 .Return,
368 .AnyFrameType,
369 .OneToken,
370 .Identifier,
371 .EnumLiteral,
372 .MultilineStringLiteral,
373 .GroupedExpression,
374 .BuiltinCallTwo,
375 .BuiltinCall,
376 .ErrorSetDecl,
377 .AnyType,
378 .Comptime,
379 .Nosuspend,
380 .Block,
381 .AsmSimple,
382 .Asm,
383 .Catch,
384 .FieldAccess,
385 .UnwrapOptional,
386 .EqualEqual,
387 .BangEqual,
388 .LessThan,
389 .GreaterThan,
390 .LessOrEqual,
391 .GreaterOrEqual,
392 .AssignMul,
393 .AssignDiv,
394 .AssignMod,
395 .AssignAdd,
396 .AssignSub,
397 .AssignBitShiftLeft,
398 .AssignBitShiftRight,
399 .AssignBitAnd,
400 .AssignBitXor,
401 .AssignBitOr,
402 .AssignMulWrap,
403 .AssignAddWrap,
404 .AssignSubWrap,
405 .Assign,
406 .MergeErrorSets,
407 .Mul,
408 .Div,
409 .Mod,
410 .ArrayMult,
411 .MulWrap,
412 .Add,
413 .Sub,
414 .ArrayCat,
415 .AddWrap,
416 .SubWrap,
417 .BitShiftLeft,
418 .BitShiftRight,
419 .BitAnd,
420 .BitXor,
421 .BitOr,
422 .OrElse,
423 .BoolAnd,
424 .BoolOr,
425 .SliceOpen,
426 .Slice,
427 .Deref,
428 .ArrayAccess,
429 .ArrayInitOne,
430 .ArrayInit,
431 .StructInitOne,
432 .CallOne,
433 .Call,
434 .SwitchCaseOne,
435 .SwitchRange,
436 .FnDecl,
437 .GlobalVarDecl,
438 .LocalVarDecl,
439 .SimpleVarDecl,
440 .AlignedVarDecl,
441 .ArrayType,
442 .ArrayTypeSentinel,
443 .PtrTypeAligned,
444 .PtrTypeSentinel,
445 .PtrType,
446 .SliceType,
447 .StructInit,
448 .SwitchCaseMulti,
449 .WhileSimple,
450 .WhileSimpleOptional,
451 .WhileCont,
452 .WhileContOptional,
453 .While,
454 .WhileOptional,
455 .WhileError,
456 .ForSimple,
457 .For,
458 .FnProtoSimple,
459 .FnProtoSimpleMulti,
460 .FnProtoOne,
461 .FnProto,
462 .ContainerDecl,
463 .ContainerDeclArg,
464 .TaggedUnion,
465 .TaggedUnionEnumTag,
466 .ContainerFieldInit,
467 .ContainerFieldAlign,
468 .ContainerField,
469 .AsmOutput,
470 .AsmInput,
471 .ErrorValue,
472 .ErrorUnion,
473 => @panic("TODO finish implementing lastToken"),
204 }474 }
205 return index;
206 }475 }
207};476};
208477
...@@ -454,7 +723,7 @@ pub const Node = struct {...@@ -454,7 +723,7 @@ pub const Node = struct {
454 /// lhs is test name token (must be string literal), if any.723 /// lhs is test name token (must be string literal), if any.
455 /// rhs is the body node.724 /// rhs is the body node.
456 TestDecl,725 TestDecl,
457 /// lhs is the index into global_var_decl_list.726 /// lhs is the index into extra_data.
458 /// rhs is the initialization expression, if any.727 /// rhs is the initialization expression, if any.
459 GlobalVarDecl,728 GlobalVarDecl,
460 /// `var a: x align(y) = rhs`729 /// `var a: x align(y) = rhs`
...@@ -732,6 +1001,7 @@ pub const Node = struct {...@@ -732,6 +1001,7 @@ pub const Node = struct {
732 /// `nosuspend lhs`. rhs unused.1001 /// `nosuspend lhs`. rhs unused.
733 Nosuspend,1002 Nosuspend,
734 /// `{}`. `sub_list[lhs..rhs]`.1003 /// `{}`. `sub_list[lhs..rhs]`.
1004 /// main_token points at the `{`.
735 Block,1005 Block,
736 /// `asm(lhs)`. rhs unused.1006 /// `asm(lhs)`. rhs unused.
737 AsmSimple,1007 AsmSimple,
lib/std/zig/parse.zig+1-1
...@@ -594,7 +594,7 @@ const Parser = struct {...@@ -594,7 +594,7 @@ const Parser = struct {
594 p.eatToken(.Keyword_var) orelse594 p.eatToken(.Keyword_var) orelse
595 return null_node;595 return null_node;
596596
597 const name_token = try p.expectToken(.Identifier);597 _ = try p.expectToken(.Identifier);
598 const type_node: Node.Index = if (p.eatToken(.Colon) == null) 0 else try p.expectTypeExpr();598 const type_node: Node.Index = if (p.eatToken(.Colon) == null) 0 else try p.expectTypeExpr();
599 const align_node = try p.parseByteAlign();599 const align_node = try p.parseByteAlign();
600 const section_node = try p.parseLinkSection();600 const section_node = try p.parseLinkSection();
lib/std/zig/parser_test.zig+3702-3723
...@@ -3,3727 +3,3704 @@...@@ -3,3727 +3,3704 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6test "zig fmt: convert var to anytype" {6test "zig fmt: simple top level comptime block" {
7 // TODO remove in next release cycle7 try testCanonical(
8 try testTransform(8 \\comptime {}
9 \\pub fn main(9 \\
10 \\ a: var,10 );
11 \\ bar: var,11}
12 \\) void {}12
13 ,13//test "recovery: top level" {
14 \\pub fn main(14// try testError(
15 \\ a: anytype,15// \\test "" {inline}
16 \\ bar: anytype,16// \\test "" {inline}
17 \\) void {}17// , &[_]Error{
18 \\18// .ExpectedInlinable,
19 );19// .ExpectedInlinable,
20}20// });
2121//}
22test "zig fmt: noasync to nosuspend" {22//
23 // TODO: remove this23//test "recovery: block statements" {
24 try testTransform(24// try testError(
25 \\pub fn main() void {25// \\test "" {
26 \\ noasync call();26// \\ foo + +;
27 \\}27// \\ inline;
28 ,28// \\}
29 \\pub fn main() void {29// , &[_]Error{
30 \\ nosuspend call();30// .InvalidToken,
31 \\}31// .ExpectedInlinable,
32 \\32// });
33 );33//}
34}34//
3535//test "recovery: missing comma" {
36test "recovery: top level" {36// try testError(
37 try testError(37// \\test "" {
38 \\test "" {inline}38// \\ switch (foo) {
39 \\test "" {inline}39// \\ 2 => {}
40 , &[_]Error{40// \\ 3 => {}
41 .ExpectedInlinable,41// \\ else => {
42 .ExpectedInlinable,42// \\ foo && bar +;
43 });43// \\ }
44}44// \\ }
4545// \\}
46test "recovery: block statements" {46// , &[_]Error{
47 try testError(47// .ExpectedToken,
48 \\test "" {48// .ExpectedToken,
49 \\ foo + +;49// .InvalidAnd,
50 \\ inline;50// .InvalidToken,
51 \\}51// });
52 , &[_]Error{52//}
53 .InvalidToken,53//
54 .ExpectedInlinable,54//test "recovery: extra qualifier" {
55 });55// try testError(
56}56// \\const a: *const const u8;
5757// \\test ""
58test "recovery: missing comma" {58// , &[_]Error{
59 try testError(59// .ExtraConstQualifier,
60 \\test "" {60// .ExpectedLBrace,
61 \\ switch (foo) {61// });
62 \\ 2 => {}62//}
63 \\ 3 => {}63//
64 \\ else => {64//test "recovery: missing return type" {
65 \\ foo && bar +;65// try testError(
66 \\ }66// \\fn foo() {
67 \\ }67// \\ a && b;
68 \\}68// \\}
69 , &[_]Error{69// \\test ""
70 .ExpectedToken,70// , &[_]Error{
71 .ExpectedToken,71// .ExpectedReturnType,
72 .InvalidAnd,72// .InvalidAnd,
73 .InvalidToken,73// .ExpectedLBrace,
74 });74// });
75}75//}
7676//
77test "recovery: extra qualifier" {77//test "recovery: continue after invalid decl" {
78 try testError(78// try testError(
79 \\const a: *const const u8;79// \\fn foo {
80 \\test ""80// \\ inline;
81 , &[_]Error{81// \\}
82 .ExtraConstQualifier,82// \\pub test "" {
83 .ExpectedLBrace,83// \\ async a && b;
84 });84// \\}
85}85// , &[_]Error{
8686// .ExpectedToken,
87test "recovery: missing return type" {87// .ExpectedPubItem,
88 try testError(88// .ExpectedParamList,
89 \\fn foo() {89// .InvalidAnd,
90 \\ a && b;90// });
91 \\}91// try testError(
92 \\test ""92// \\threadlocal test "" {
93 , &[_]Error{93// \\ @a && b;
94 .ExpectedReturnType,94// \\}
95 .InvalidAnd,95// , &[_]Error{
96 .ExpectedLBrace,96// .ExpectedVarDecl,
97 });97// .ExpectedParamList,
98}98// .InvalidAnd,
9999// });
100test "recovery: continue after invalid decl" {100//}
101 try testError(101//
102 \\fn foo {102//test "recovery: invalid extern/inline" {
103 \\ inline;103// try testError(
104 \\}104// \\inline test "" { a && b; }
105 \\pub test "" {105// , &[_]Error{
106 \\ async a && b;106// .ExpectedFn,
107 \\}107// .InvalidAnd,
108 , &[_]Error{108// });
109 .ExpectedToken,109// try testError(
110 .ExpectedPubItem,110// \\extern "" test "" { a && b; }
111 .ExpectedParamList,111// , &[_]Error{
112 .InvalidAnd,112// .ExpectedVarDeclOrFn,
113 });113// .InvalidAnd,
114 try testError(114// });
115 \\threadlocal test "" {115//}
116 \\ @a && b;116//
117 \\}117//test "recovery: missing semicolon" {
118 , &[_]Error{118// try testError(
119 .ExpectedVarDecl,119// \\test "" {
120 .ExpectedParamList,120// \\ comptime a && b
121 .InvalidAnd,121// \\ c && d
122 });122// \\ @foo
123}123// \\}
124124// , &[_]Error{
125test "recovery: invalid extern/inline" {125// .InvalidAnd,
126 try testError(126// .ExpectedToken,
127 \\inline test "" { a && b; }127// .InvalidAnd,
128 , &[_]Error{128// .ExpectedToken,
129 .ExpectedFn,129// .ExpectedParamList,
130 .InvalidAnd,130// .ExpectedToken,
131 });131// });
132 try testError(132//}
133 \\extern "" test "" { a && b; }133//
134 , &[_]Error{134//test "recovery: invalid container members" {
135 .ExpectedVarDeclOrFn,135// try testError(
136 .InvalidAnd,136// \\usingnamespace;
137 });137// \\foo+
138}138// \\bar@,
139139// \\while (a == 2) { test "" {}}
140test "recovery: missing semicolon" {140// \\test "" {
141 try testError(141// \\ a && b
142 \\test "" {142// \\}
143 \\ comptime a && b143// , &[_]Error{
144 \\ c && d144// .ExpectedExpr,
145 \\ @foo145// .ExpectedToken,
146 \\}146// .ExpectedToken,
147 , &[_]Error{147// .ExpectedContainerMembers,
148 .InvalidAnd,148// .InvalidAnd,
149 .ExpectedToken,149// .ExpectedToken,
150 .InvalidAnd,150// });
151 .ExpectedToken,151//}
152 .ExpectedParamList,152//
153 .ExpectedToken,153//test "recovery: invalid parameter" {
154 });154// try testError(
155}155// \\fn main() void {
156156// \\ a(comptime T: type)
157test "recovery: invalid container members" {157// \\}
158 try testError(158// , &[_]Error{
159 \\usingnamespace;159// .ExpectedToken,
160 \\foo+160// });
161 \\bar@,161//}
162 \\while (a == 2) { test "" {}}162//
163 \\test "" {163//test "recovery: extra '}' at top level" {
164 \\ a && b164// try testError(
165 \\}165// \\}}}
166 , &[_]Error{166// \\test "" {
167 .ExpectedExpr,167// \\ a && b;
168 .ExpectedToken,168// \\}
169 .ExpectedToken,169// , &[_]Error{
170 .ExpectedContainerMembers,170// .ExpectedContainerMembers,
171 .InvalidAnd,171// .ExpectedContainerMembers,
172 .ExpectedToken,172// .ExpectedContainerMembers,
173 });173// .InvalidAnd,
174}174// });
175175//}
176test "recovery: invalid parameter" {176//
177 try testError(177//test "recovery: mismatched bracket at top level" {
178 \\fn main() void {178// try testError(
179 \\ a(comptime T: type)179// \\const S = struct {
180 \\}180// \\ arr: 128]?G
181 , &[_]Error{181// \\};
182 .ExpectedToken,182// , &[_]Error{
183 });183// .ExpectedToken,
184}184// });
185185//}
186test "recovery: extra '}' at top level" {186//
187 try testError(187//test "recovery: invalid global error set access" {
188 \\}}}188// try testError(
189 \\test "" {189// \\test "" {
190 \\ a && b;190// \\ error && foo;
191 \\}191// \\}
192 , &[_]Error{192// , &[_]Error{
193 .ExpectedContainerMembers,193// .ExpectedToken,
194 .ExpectedContainerMembers,194// .ExpectedIdentifier,
195 .ExpectedContainerMembers,195// .InvalidAnd,
196 .InvalidAnd,196// });
197 });197//}
198}198//
199199//test "recovery: invalid asterisk after pointer dereference" {
200test "recovery: mismatched bracket at top level" {200// try testError(
201 try testError(201// \\test "" {
202 \\const S = struct {202// \\ var sequence = "repeat".*** 10;
203 \\ arr: 128]?G203// \\}
204 \\};204// , &[_]Error{
205 , &[_]Error{205// .AsteriskAfterPointerDereference,
206 .ExpectedToken,206// });
207 });207// try testError(
208}208// \\test "" {
209209// \\ var sequence = "repeat".** 10&&a;
210test "recovery: invalid global error set access" {210// \\}
211 try testError(211// , &[_]Error{
212 \\test "" {212// .AsteriskAfterPointerDereference,
213 \\ error && foo;213// .InvalidAnd,
214 \\}214// });
215 , &[_]Error{215//}
216 .ExpectedToken,216//
217 .ExpectedIdentifier,217//test "recovery: missing semicolon after if, for, while stmt" {
218 .InvalidAnd,218// try testError(
219 });219// \\test "" {
220}220// \\ if (foo) bar
221221// \\ for (foo) |a| bar
222test "recovery: invalid asterisk after pointer dereference" {222// \\ while (foo) bar
223 try testError(223// \\ a && b;
224 \\test "" {224// \\}
225 \\ var sequence = "repeat".*** 10;225// , &[_]Error{
226 \\}226// .ExpectedSemiOrElse,
227 , &[_]Error{227// .ExpectedSemiOrElse,
228 .AsteriskAfterPointerDereference,228// .ExpectedSemiOrElse,
229 });229// .InvalidAnd,
230 try testError(230// });
231 \\test "" {231//}
232 \\ var sequence = "repeat".** 10&&a;232//
233 \\}233//test "recovery: invalid comptime" {
234 , &[_]Error{234// try testError(
235 .AsteriskAfterPointerDereference,235// \\comptime
236 .InvalidAnd,236// , &[_]Error{
237 });237// .ExpectedBlockOrField,
238}238// });
239239//}
240test "recovery: missing semicolon after if, for, while stmt" {240//
241 try testError(241//test "recovery: missing block after for/while loops" {
242 \\test "" {242// try testError(
243 \\ if (foo) bar243// \\test "" { while (foo) }
244 \\ for (foo) |a| bar244// , &[_]Error{
245 \\ while (foo) bar245// .ExpectedBlockOrAssignment,
246 \\ a && b;246// });
247 \\}247// try testError(
248 , &[_]Error{248// \\test "" { for (foo) |bar| }
249 .ExpectedSemiOrElse,249// , &[_]Error{
250 .ExpectedSemiOrElse,250// .ExpectedBlockOrAssignment,
251 .ExpectedSemiOrElse,251// });
252 .InvalidAnd,252//}
253 });253//
254}254//test "zig fmt: respect line breaks after var declarations" {
255255// try testCanonical(
256test "recovery: invalid comptime" {256// \\const crc =
257 try testError(257// \\ lookup_tables[0][p[7]] ^
258 \\comptime258// \\ lookup_tables[1][p[6]] ^
259 , &[_]Error{259// \\ lookup_tables[2][p[5]] ^
260 .ExpectedBlockOrField,260// \\ lookup_tables[3][p[4]] ^
261 });261// \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
262}262// \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
263263// \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
264test "recovery: missing block after for/while loops" {264// \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
265 try testError(265// \\
266 \\test "" { while (foo) }266// );
267 , &[_]Error{267//}
268 .ExpectedBlockOrAssignment,268//
269 });269//test "zig fmt: multiline string mixed with comments" {
270 try testError(270// try testCanonical(
271 \\test "" { for (foo) |bar| }271// \\const s1 =
272 , &[_]Error{272// \\ //\\one
273 .ExpectedBlockOrAssignment,273// \\ \\two)
274 });274// \\ \\three
275}275// \\;
276276// \\const s2 =
277test "zig fmt: respect line breaks after var declarations" {277// \\ \\one
278 try testCanonical(278// \\ \\two)
279 \\const crc =279// \\ //\\three
280 \\ lookup_tables[0][p[7]] ^280// \\;
281 \\ lookup_tables[1][p[6]] ^281// \\const s3 =
282 \\ lookup_tables[2][p[5]] ^282// \\ \\one
283 \\ lookup_tables[3][p[4]] ^283// \\ //\\two)
284 \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^284// \\ \\three
285 \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^285// \\;
286 \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^286// \\const s4 =
287 \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];287// \\ \\one
288 \\288// \\ //\\two
289 );289// \\ \\three
290}290// \\ //\\four
291291// \\ \\five
292test "zig fmt: multiline string mixed with comments" {292// \\;
293 try testCanonical(293// \\const a =
294 \\const s1 =294// \\ 1;
295 \\ //\\one295// \\
296 \\ \\two)296// );
297 \\ \\three297//}
298 \\;298//
299 \\const s2 =299//test "zig fmt: empty file" {
300 \\ \\one300// try testCanonical(
301 \\ \\two)301// \\
302 \\ //\\three302// );
303 \\;303//}
304 \\const s3 =304//
305 \\ \\one305//test "zig fmt: if statment" {
306 \\ //\\two)306// try testCanonical(
307 \\ \\three307// \\test "" {
308 \\;308// \\ if (optional()) |some|
309 \\const s4 =309// \\ bar = some.foo();
310 \\ \\one310// \\}
311 \\ //\\two311// \\
312 \\ \\three312// );
313 \\ //\\four313//}
314 \\ \\five314//
315 \\;315//test "zig fmt: top-level fields" {
316 \\const a =316// try testCanonical(
317 \\ 1;317// \\a: did_you_know,
318 \\318// \\b: all_files_are,
319 );319// \\structs: ?x,
320}320// \\
321321// );
322test "zig fmt: empty file" {322//}
323 try testCanonical(323//
324 \\324//test "zig fmt: decl between fields" {
325 );325// try testError(
326}326// \\const S = struct {
327327// \\ const foo = 2;
328test "zig fmt: if statment" {328// \\ const bar = 2;
329 try testCanonical(329// \\ const baz = 2;
330 \\test "" {330// \\ a: usize,
331 \\ if (optional()) |some|331// \\ const foo1 = 2;
332 \\ bar = some.foo();332// \\ const bar1 = 2;
333 \\}333// \\ const baz1 = 2;
334 \\334// \\ b: usize,
335 );335// \\};
336}336// , &[_]Error{
337337// .DeclBetweenFields,
338test "zig fmt: top-level fields" {338// });
339 try testCanonical(339//}
340 \\a: did_you_know,340//
341 \\b: all_files_are,341//test "zig fmt: eof after missing comma" {
342 \\structs: ?x,342// try testError(
343 \\343// \\foo()
344 );344// , &[_]Error{
345}345// .ExpectedToken,
346346// });
347test "zig fmt: decl between fields" {347//}
348 try testError(348//
349 \\const S = struct {349//test "zig fmt: errdefer with payload" {
350 \\ const foo = 2;350// try testCanonical(
351 \\ const bar = 2;351// \\pub fn main() anyerror!void {
352 \\ const baz = 2;352// \\ errdefer |a| x += 1;
353 \\ a: usize,353// \\ errdefer |a| {}
354 \\ const foo1 = 2;354// \\ errdefer |a| {
355 \\ const bar1 = 2;355// \\ x += 1;
356 \\ const baz1 = 2;356// \\ }
357 \\ b: usize,357// \\}
358 \\};358// \\
359 , &[_]Error{359// );
360 .DeclBetweenFields,360//}
361 });361//
362}362//test "zig fmt: nosuspend block" {
363363// try testCanonical(
364test "zig fmt: eof after missing comma" {364// \\pub fn main() anyerror!void {
365 try testError(365// \\ nosuspend {
366 \\foo()366// \\ var foo: Foo = .{ .bar = 42 };
367 , &[_]Error{367// \\ }
368 .ExpectedToken,368// \\}
369 });369// \\
370}370// );
371371//}
372test "zig fmt: errdefer with payload" {372//
373 try testCanonical(373//test "zig fmt: nosuspend await" {
374 \\pub fn main() anyerror!void {374// try testCanonical(
375 \\ errdefer |a| x += 1;375// \\fn foo() void {
376 \\ errdefer |a| {}376// \\ x = nosuspend await y;
377 \\ errdefer |a| {377// \\}
378 \\ x += 1;378// \\
379 \\ }379// );
380 \\}380//}
381 \\381//
382 );382//test "zig fmt: trailing comma in container declaration" {
383}383// try testCanonical(
384384// \\const X = struct { foo: i32 };
385test "zig fmt: nosuspend block" {385// \\const X = struct { foo: i32, bar: i32 };
386 try testCanonical(386// \\const X = struct { foo: i32 = 1, bar: i32 = 2 };
387 \\pub fn main() anyerror!void {387// \\const X = struct { foo: i32 align(4), bar: i32 align(4) };
388 \\ nosuspend {388// \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };
389 \\ var foo: Foo = .{ .bar = 42 };389// \\
390 \\ }390// );
391 \\}391// try testCanonical(
392 \\392// \\test "" {
393 );393// \\ comptime {
394}394// \\ const X = struct {
395395// \\ x: i32
396test "zig fmt: nosuspend await" {396// \\ };
397 try testCanonical(397// \\ }
398 \\fn foo() void {398// \\}
399 \\ x = nosuspend await y;399// \\
400 \\}400// );
401 \\401// try testTransform(
402 );402// \\const X = struct {
403}403// \\ foo: i32, bar: i8 };
404404// ,
405test "zig fmt: trailing comma in container declaration" {405// \\const X = struct {
406 try testCanonical(406// \\ foo: i32, bar: i8
407 \\const X = struct { foo: i32 };407// \\};
408 \\const X = struct { foo: i32, bar: i32 };408// \\
409 \\const X = struct { foo: i32 = 1, bar: i32 = 2 };409// );
410 \\const X = struct { foo: i32 align(4), bar: i32 align(4) };410//}
411 \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };411//
412 \\412//test "zig fmt: trailing comma in fn parameter list" {
413 );413// try testCanonical(
414 try testCanonical(414// \\pub fn f(
415 \\test "" {415// \\ a: i32,
416 \\ comptime {416// \\ b: i32,
417 \\ const X = struct {417// \\) i32 {}
418 \\ x: i32418// \\pub fn f(
419 \\ };419// \\ a: i32,
420 \\ }420// \\ b: i32,
421 \\}421// \\) align(8) i32 {}
422 \\422// \\pub fn f(
423 );423// \\ a: i32,
424 try testTransform(424// \\ b: i32,
425 \\const X = struct {425// \\) linksection(".text") i32 {}
426 \\ foo: i32, bar: i8 };426// \\pub fn f(
427 ,427// \\ a: i32,
428 \\const X = struct {428// \\ b: i32,
429 \\ foo: i32, bar: i8429// \\) callconv(.C) i32 {}
430 \\};430// \\pub fn f(
431 \\431// \\ a: i32,
432 );432// \\ b: i32,
433}433// \\) align(8) linksection(".text") i32 {}
434434// \\pub fn f(
435test "zig fmt: trailing comma in fn parameter list" {435// \\ a: i32,
436 try testCanonical(436// \\ b: i32,
437 \\pub fn f(437// \\) align(8) callconv(.C) i32 {}
438 \\ a: i32,438// \\pub fn f(
439 \\ b: i32,439// \\ a: i32,
440 \\) i32 {}440// \\ b: i32,
441 \\pub fn f(441// \\) align(8) linksection(".text") callconv(.C) i32 {}
442 \\ a: i32,442// \\pub fn f(
443 \\ b: i32,443// \\ a: i32,
444 \\) align(8) i32 {}444// \\ b: i32,
445 \\pub fn f(445// \\) linksection(".text") callconv(.C) i32 {}
446 \\ a: i32,446// \\
447 \\ b: i32,447// );
448 \\) linksection(".text") i32 {}448//}
449 \\pub fn f(449//
450 \\ a: i32,450//test "zig fmt: comptime struct field" {
451 \\ b: i32,451// try testCanonical(
452 \\) callconv(.C) i32 {}452// \\const Foo = struct {
453 \\pub fn f(453// \\ a: i32,
454 \\ a: i32,454// \\ comptime b: i32 = 1234,
455 \\ b: i32,455// \\};
456 \\) align(8) linksection(".text") i32 {}456// \\
457 \\pub fn f(457// );
458 \\ a: i32,458//}
459 \\ b: i32,459//
460 \\) align(8) callconv(.C) i32 {}460//test "zig fmt: c pointer type" {
461 \\pub fn f(461// try testCanonical(
462 \\ a: i32,462// \\pub extern fn repro() [*c]const u8;
463 \\ b: i32,463// \\
464 \\) align(8) linksection(".text") callconv(.C) i32 {}464// );
465 \\pub fn f(465//}
466 \\ a: i32,466//
467 \\ b: i32,467//test "zig fmt: builtin call with trailing comma" {
468 \\) linksection(".text") callconv(.C) i32 {}468// try testCanonical(
469 \\469// \\pub fn main() void {
470 );470// \\ @breakpoint();
471}471// \\ _ = @boolToInt(a);
472472// \\ _ = @call(
473test "zig fmt: comptime struct field" {473// \\ a,
474 try testCanonical(474// \\ b,
475 \\const Foo = struct {475// \\ c,
476 \\ a: i32,476// \\ );
477 \\ comptime b: i32 = 1234,477// \\}
478 \\};478// \\
479 \\479// );
480 );480//}
481}481//
482482//test "zig fmt: asm expression with comptime content" {
483test "zig fmt: c pointer type" {483// try testCanonical(
484 try testCanonical(484// \\comptime {
485 \\pub extern fn repro() [*c]const u8;485// \\ asm ("foo" ++ "bar");
486 \\486// \\}
487 );487// \\pub fn main() void {
488}488// \\ asm volatile ("foo" ++ "bar");
489489// \\ asm volatile ("foo" ++ "bar"
490test "zig fmt: builtin call with trailing comma" {490// \\ : [_] "" (x)
491 try testCanonical(491// \\ );
492 \\pub fn main() void {492// \\ asm volatile ("foo" ++ "bar"
493 \\ @breakpoint();493// \\ : [_] "" (x)
494 \\ _ = @boolToInt(a);494// \\ : [_] "" (y)
495 \\ _ = @call(495// \\ );
496 \\ a,496// \\ asm volatile ("foo" ++ "bar"
497 \\ b,497// \\ : [_] "" (x)
498 \\ c,498// \\ : [_] "" (y)
499 \\ );499// \\ : "h", "e", "l", "l", "o"
500 \\}500// \\ );
501 \\501// \\}
502 );502// \\
503}503// );
504504//}
505test "zig fmt: asm expression with comptime content" {505//
506 try testCanonical(506//test "zig fmt: anytype struct field" {
507 \\comptime {507// try testCanonical(
508 \\ asm ("foo" ++ "bar");508// \\pub const Pointer = struct {
509 \\}509// \\ sentinel: anytype,
510 \\pub fn main() void {510// \\};
511 \\ asm volatile ("foo" ++ "bar");511// \\
512 \\ asm volatile ("foo" ++ "bar"512// );
513 \\ : [_] "" (x)513//}
514 \\ );514//
515 \\ asm volatile ("foo" ++ "bar"515//test "zig fmt: sentinel-terminated array type" {
516 \\ : [_] "" (x)516// try testCanonical(
517 \\ : [_] "" (y)517// \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
518 \\ );518// \\ return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
519 \\ asm volatile ("foo" ++ "bar"519// \\}
520 \\ : [_] "" (x)520// \\
521 \\ : [_] "" (y)521// );
522 \\ : "h", "e", "l", "l", "o"522//}
523 \\ );523//
524 \\}524//test "zig fmt: sentinel-terminated slice type" {
525 \\525// try testCanonical(
526 );526// \\pub fn toSlice(self: Buffer) [:0]u8 {
527}527// \\ return self.list.toSlice()[0..self.len()];
528528// \\}
529test "zig fmt: anytype struct field" {529// \\
530 try testCanonical(530// );
531 \\pub const Pointer = struct {531//}
532 \\ sentinel: anytype,532//
533 \\};533//test "zig fmt: anon literal in array" {
534 \\534// try testCanonical(
535 );535// \\var arr: [2]Foo = .{
536}536// \\ .{ .a = 2 },
537537// \\ .{ .b = 3 },
538test "zig fmt: sentinel-terminated array type" {538// \\};
539 try testCanonical(539// \\
540 \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {540// );
541 \\ return sliceToPrefixedFileW(mem.toSliceConst(u8, s));541//}
542 \\}542//
543 \\543//test "zig fmt: alignment in anonymous literal" {
544 );544// try testTransform(
545}545// \\const a = .{
546546// \\ "U", "L", "F",
547test "zig fmt: sentinel-terminated slice type" {547// \\ "U'",
548 try testCanonical(548// \\ "L'",
549 \\pub fn toSlice(self: Buffer) [:0]u8 {549// \\ "F'",
550 \\ return self.list.toSlice()[0..self.len()];550// \\};
551 \\}551// \\
552 \\552// ,
553 );553// \\const a = .{
554}554// \\ "U", "L", "F",
555555// \\ "U'", "L'", "F'",
556test "zig fmt: anon literal in array" {556// \\};
557 try testCanonical(557// \\
558 \\var arr: [2]Foo = .{558// );
559 \\ .{ .a = 2 },559//}
560 \\ .{ .b = 3 },560//
561 \\};561//test "zig fmt: anon struct literal syntax" {
562 \\562// try testCanonical(
563 );563// \\const x = .{
564}564// \\ .a = b,
565565// \\ .c = d,
566test "zig fmt: alignment in anonymous literal" {566// \\};
567 try testTransform(567// \\
568 \\const a = .{568// );
569 \\ "U", "L", "F",569//}
570 \\ "U'",570//
571 \\ "L'",571//test "zig fmt: anon list literal syntax" {
572 \\ "F'",572// try testCanonical(
573 \\};573// \\const x = .{ a, b, c };
574 \\574// \\
575 ,575// );
576 \\const a = .{576//}
577 \\ "U", "L", "F",577//
578 \\ "U'", "L'", "F'",578//test "zig fmt: async function" {
579 \\};579// try testCanonical(
580 \\580// \\pub const Server = struct {
581 );581// \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void,
582}582// \\};
583583// \\test "hi" {
584test "zig fmt: anon struct literal syntax" {584// \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
585 try testCanonical(585// \\}
586 \\const x = .{586// \\
587 \\ .a = b,587// );
588 \\ .c = d,588//}
589 \\};589//
590 \\590//test "zig fmt: whitespace fixes" {
591 );591// try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",
592}592// \\test "" {
593593// \\ const hi = x;
594test "zig fmt: anon list literal syntax" {594// \\}
595 try testCanonical(595// \\// zig fmt: off
596 \\const x = .{ a, b, c };596// \\test ""{
597 \\597// \\ const a = b;}
598 );598// \\
599}599// );
600600//}
601test "zig fmt: async function" {601//
602 try testCanonical(602//test "zig fmt: while else err prong with no block" {
603 \\pub const Server = struct {603// try testCanonical(
604 \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void,604// \\test "" {
605 \\};605// \\ const result = while (returnError()) |value| {
606 \\test "hi" {606// \\ break value;
607 \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);607// \\ } else |err| @as(i32, 2);
608 \\}608// \\ expect(result == 2);
609 \\609// \\}
610 );610// \\
611}611// );
612612//}
613test "zig fmt: whitespace fixes" {613//
614 try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",614//test "zig fmt: tagged union with enum values" {
615 \\test "" {615// try testCanonical(
616 \\ const hi = x;616// \\const MultipleChoice2 = union(enum(u32)) {
617 \\}617// \\ Unspecified1: i32,
618 \\// zig fmt: off618// \\ A: f32 = 20,
619 \\test ""{619// \\ Unspecified2: void,
620 \\ const a = b;}620// \\ B: bool = 40,
621 \\621// \\ Unspecified3: i32,
622 );622// \\ C: i8 = 60,
623}623// \\ Unspecified4: void,
624624// \\ D: void = 1000,
625test "zig fmt: while else err prong with no block" {625// \\ Unspecified5: i32,
626 try testCanonical(626// \\};
627 \\test "" {627// \\
628 \\ const result = while (returnError()) |value| {628// );
629 \\ break value;629//}
630 \\ } else |err| @as(i32, 2);630//
631 \\ expect(result == 2);631//test "zig fmt: allowzero pointer" {
632 \\}632// try testCanonical(
633 \\633// \\const T = [*]allowzero const u8;
634 );634// \\
635}635// );
636636//}
637test "zig fmt: tagged union with enum values" {637//
638 try testCanonical(638//test "zig fmt: enum literal" {
639 \\const MultipleChoice2 = union(enum(u32)) {639// try testCanonical(
640 \\ Unspecified1: i32,640// \\const x = .hi;
641 \\ A: f32 = 20,641// \\
642 \\ Unspecified2: void,642// );
643 \\ B: bool = 40,643//}
644 \\ Unspecified3: i32,644//
645 \\ C: i8 = 60,645//test "zig fmt: enum literal inside array literal" {
646 \\ Unspecified4: void,646// try testCanonical(
647 \\ D: void = 1000,647// \\test "enums in arrays" {
648 \\ Unspecified5: i32,648// \\ var colors = []Color{.Green};
649 \\};649// \\ colors = []Colors{ .Green, .Cyan };
650 \\650// \\ colors = []Colors{
651 );651// \\ .Grey,
652}652// \\ .Green,
653653// \\ .Cyan,
654test "zig fmt: allowzero pointer" {654// \\ };
655 try testCanonical(655// \\}
656 \\const T = [*]allowzero const u8;656// \\
657 \\657// );
658 );658//}
659}659//
660660//test "zig fmt: character literal larger than u8" {
661test "zig fmt: enum literal" {661// try testCanonical(
662 try testCanonical(662// \\const x = '\u{01f4a9}';
663 \\const x = .hi;663// \\
664 \\664// );
665 );665//}
666}666//
667667//test "zig fmt: infix operator and then multiline string literal" {
668test "zig fmt: enum literal inside array literal" {668// try testCanonical(
669 try testCanonical(669// \\const x = "" ++
670 \\test "enums in arrays" {670// \\ \\ hi
671 \\ var colors = []Color{.Green};671// \\;
672 \\ colors = []Colors{ .Green, .Cyan };672// \\
673 \\ colors = []Colors{673// );
674 \\ .Grey,674//}
675 \\ .Green,675//
676 \\ .Cyan,676//test "zig fmt: infix operator and then multiline string literal" {
677 \\ };677// try testCanonical(
678 \\}678// \\const x = "" ++
679 \\679// \\ \\ hi0
680 );680// \\ \\ hi1
681}681// \\ \\ hi2
682682// \\;
683test "zig fmt: character literal larger than u8" {683// \\
684 try testCanonical(684// );
685 \\const x = '\u{01f4a9}';685//}
686 \\686//
687 );687//test "zig fmt: C pointers" {
688}688// try testCanonical(
689689// \\const Ptr = [*c]i32;
690test "zig fmt: infix operator and then multiline string literal" {690// \\
691 try testCanonical(691// );
692 \\const x = "" ++692//}
693 \\ \\ hi693//
694 \\;694//test "zig fmt: threadlocal" {
695 \\695// try testCanonical(
696 );696// \\threadlocal var x: i32 = 1234;
697}697// \\
698698// );
699test "zig fmt: infix operator and then multiline string literal" {699//}
700 try testCanonical(700//
701 \\const x = "" ++701//test "zig fmt: linksection" {
702 \\ \\ hi0702// try testCanonical(
703 \\ \\ hi1703// \\export var aoeu: u64 linksection(".text.derp") = 1234;
704 \\ \\ hi2704// \\export fn _start() linksection(".text.boot") callconv(.Naked) noreturn {}
705 \\;705// \\
706 \\706// );
707 );707//}
708}708//
709709//test "zig fmt: correctly move doc comments on struct fields" {
710test "zig fmt: C pointers" {710// try testTransform(
711 try testCanonical(711// \\pub const section_64 = extern struct {
712 \\const Ptr = [*c]i32;712// \\ sectname: [16]u8, /// name of this section
713 \\713// \\ segname: [16]u8, /// segment this section goes in
714 );714// \\};
715}715// ,
716716// \\pub const section_64 = extern struct {
717test "zig fmt: threadlocal" {717// \\ /// name of this section
718 try testCanonical(718// \\ sectname: [16]u8,
719 \\threadlocal var x: i32 = 1234;719// \\ /// segment this section goes in
720 \\720// \\ segname: [16]u8,
721 );721// \\};
722}722// \\
723723// );
724test "zig fmt: linksection" {724//}
725 try testCanonical(725//
726 \\export var aoeu: u64 linksection(".text.derp") = 1234;726//test "zig fmt: correctly space struct fields with doc comments" {
727 \\export fn _start() linksection(".text.boot") callconv(.Naked) noreturn {}727// try testTransform(
728 \\728// \\pub const S = struct {
729 );729// \\ /// A
730}730// \\ a: u8,
731731// \\ /// B
732test "zig fmt: correctly move doc comments on struct fields" {732// \\ /// B (cont)
733 try testTransform(733// \\ b: u8,
734 \\pub const section_64 = extern struct {734// \\
735 \\ sectname: [16]u8, /// name of this section735// \\
736 \\ segname: [16]u8, /// segment this section goes in736// \\ /// C
737 \\};737// \\ c: u8,
738 ,738// \\};
739 \\pub const section_64 = extern struct {739// \\
740 \\ /// name of this section740// ,
741 \\ sectname: [16]u8,741// \\pub const S = struct {
742 \\ /// segment this section goes in742// \\ /// A
743 \\ segname: [16]u8,743// \\ a: u8,
744 \\};744// \\ /// B
745 \\745// \\ /// B (cont)
746 );746// \\ b: u8,
747}747// \\
748748// \\ /// C
749test "zig fmt: correctly space struct fields with doc comments" {749// \\ c: u8,
750 try testTransform(750// \\};
751 \\pub const S = struct {751// \\
752 \\ /// A752// );
753 \\ a: u8,753//}
754 \\ /// B754//
755 \\ /// B (cont)755//test "zig fmt: doc comments on param decl" {
756 \\ b: u8,756// try testCanonical(
757 \\757// \\pub const Allocator = struct {
758 \\758// \\ shrinkFn: fn (
759 \\ /// C759// \\ self: *Allocator,
760 \\ c: u8,760// \\ /// Guaranteed to be the same as what was returned from most recent call to
761 \\};761// \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
762 \\762// \\ old_mem: []u8,
763 ,763// \\ /// Guaranteed to be the same as what was returned from most recent call to
764 \\pub const S = struct {764// \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
765 \\ /// A765// \\ old_alignment: u29,
766 \\ a: u8,766// \\ /// Guaranteed to be less than or equal to `old_mem.len`.
767 \\ /// B767// \\ new_byte_count: usize,
768 \\ /// B (cont)768// \\ /// Guaranteed to be less than or equal to `old_alignment`.
769 \\ b: u8,769// \\ new_alignment: u29,
770 \\770// \\ ) []u8,
771 \\ /// C771// \\};
772 \\ c: u8,772// \\
773 \\};773// );
774 \\774//}
775 );775//
776}776//test "zig fmt: aligned struct field" {
777777// try testCanonical(
778test "zig fmt: doc comments on param decl" {778// \\pub const S = struct {
779 try testCanonical(779// \\ f: i32 align(32),
780 \\pub const Allocator = struct {780// \\};
781 \\ shrinkFn: fn (781// \\
782 \\ self: *Allocator,782// );
783 \\ /// Guaranteed to be the same as what was returned from most recent call to783// try testCanonical(
784 \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.784// \\pub const S = struct {
785 \\ old_mem: []u8,785// \\ f: i32 align(32) = 1,
786 \\ /// Guaranteed to be the same as what was returned from most recent call to786// \\};
787 \\ /// `allocFn`, `reallocFn`, or `shrinkFn`.787// \\
788 \\ old_alignment: u29,788// );
789 \\ /// Guaranteed to be less than or equal to `old_mem.len`.789//}
790 \\ new_byte_count: usize,790//
791 \\ /// Guaranteed to be less than or equal to `old_alignment`.791//test "zig fmt: comment to disable/enable zig fmt first" {
792 \\ new_alignment: u29,792// try testCanonical(
793 \\ ) []u8,793// \\// Test trailing comma syntax
794 \\};794// \\// zig fmt: off
795 \\795// \\
796 );796// \\const struct_trailing_comma = struct { x: i32, y: i32, };
797}797// );
798798//}
799test "zig fmt: aligned struct field" {799//
800 try testCanonical(800//test "zig fmt: comment to disable/enable zig fmt" {
801 \\pub const S = struct {801// try testTransform(
802 \\ f: i32 align(32),802// \\const a = b;
803 \\};803// \\// zig fmt: off
804 \\804// \\const c = d;
805 );805// \\// zig fmt: on
806 try testCanonical(806// \\const e = f;
807 \\pub const S = struct {807// ,
808 \\ f: i32 align(32) = 1,808// \\const a = b;
809 \\};809// \\// zig fmt: off
810 \\810// \\const c = d;
811 );811// \\// zig fmt: on
812}812// \\const e = f;
813813// \\
814test "zig fmt: comment to disable/enable zig fmt first" {814// );
815 try testCanonical(815//}
816 \\// Test trailing comma syntax816//
817 \\// zig fmt: off817//test "zig fmt: line comment following 'zig fmt: off'" {
818 \\818// try testCanonical(
819 \\const struct_trailing_comma = struct { x: i32, y: i32, };819// \\// zig fmt: off
820 );820// \\// Test
821}821// \\const e = f;
822822// );
823test "zig fmt: comment to disable/enable zig fmt" {823//}
824 try testTransform(824//
825 \\const a = b;825//test "zig fmt: doc comment following 'zig fmt: off'" {
826 \\// zig fmt: off826// try testCanonical(
827 \\const c = d;827// \\// zig fmt: off
828 \\// zig fmt: on828// \\/// test
829 \\const e = f;829// \\const e = f;
830 ,830// );
831 \\const a = b;831//}
832 \\// zig fmt: off832//
833 \\const c = d;833//test "zig fmt: line and doc comment following 'zig fmt: off'" {
834 \\// zig fmt: on834// try testCanonical(
835 \\const e = f;835// \\// zig fmt: off
836 \\836// \\// test 1
837 );837// \\/// test 2
838}838// \\const e = f;
839839// );
840test "zig fmt: line comment following 'zig fmt: off'" {840//}
841 try testCanonical(841//
842 \\// zig fmt: off842//test "zig fmt: doc and line comment following 'zig fmt: off'" {
843 \\// Test843// try testCanonical(
844 \\const e = f;844// \\// zig fmt: off
845 );845// \\/// test 1
846}846// \\// test 2
847847// \\const e = f;
848test "zig fmt: doc comment following 'zig fmt: off'" {848// );
849 try testCanonical(849//}
850 \\// zig fmt: off850//
851 \\/// test851//test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
852 \\const e = f;852// try testCanonical(
853 );853// \\// zig fmt: off
854}854// \\// zig fmt: on
855855// \\// zig fmt: off
856test "zig fmt: line and doc comment following 'zig fmt: off'" {856// \\const e = f;
857 try testCanonical(857// \\// zig fmt: off
858 \\// zig fmt: off858// \\// zig fmt: on
859 \\// test 1859// \\// zig fmt: off
860 \\/// test 2860// \\const a = b;
861 \\const e = f;861// \\// zig fmt: on
862 );862// \\const c = d;
863}863// \\// zig fmt: on
864864// \\
865test "zig fmt: doc and line comment following 'zig fmt: off'" {865// );
866 try testCanonical(866//}
867 \\// zig fmt: off867//
868 \\/// test 1868//test "zig fmt: line comment following 'zig fmt: on'" {
869 \\// test 2869// try testCanonical(
870 \\const e = f;870// \\// zig fmt: off
871 );871// \\const e = f;
872}872// \\// zig fmt: on
873873// \\// test
874test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {874// \\const e = f;
875 try testCanonical(875// \\
876 \\// zig fmt: off876// );
877 \\// zig fmt: on877//}
878 \\// zig fmt: off878//
879 \\const e = f;879//test "zig fmt: doc comment following 'zig fmt: on'" {
880 \\// zig fmt: off880// try testCanonical(
881 \\// zig fmt: on881// \\// zig fmt: off
882 \\// zig fmt: off882// \\const e = f;
883 \\const a = b;883// \\// zig fmt: on
884 \\// zig fmt: on884// \\/// test
885 \\const c = d;885// \\const e = f;
886 \\// zig fmt: on886// \\
887 \\887// );
888 );888//}
889}889//
890890//test "zig fmt: line and doc comment following 'zig fmt: on'" {
891test "zig fmt: line comment following 'zig fmt: on'" {891// try testCanonical(
892 try testCanonical(892// \\// zig fmt: off
893 \\// zig fmt: off893// \\const e = f;
894 \\const e = f;894// \\// zig fmt: on
895 \\// zig fmt: on895// \\// test1
896 \\// test896// \\/// test2
897 \\const e = f;897// \\const e = f;
898 \\898// \\
899 );899// );
900}900//}
901901//
902test "zig fmt: doc comment following 'zig fmt: on'" {902//test "zig fmt: doc and line comment following 'zig fmt: on'" {
903 try testCanonical(903// try testCanonical(
904 \\// zig fmt: off904// \\// zig fmt: off
905 \\const e = f;905// \\const e = f;
906 \\// zig fmt: on906// \\// zig fmt: on
907 \\/// test907// \\/// test1
908 \\const e = f;908// \\// test2
909 \\909// \\const e = f;
910 );910// \\
911}911// );
912912//}
913test "zig fmt: line and doc comment following 'zig fmt: on'" {913//
914 try testCanonical(914//test "zig fmt: pointer of unknown length" {
915 \\// zig fmt: off915// try testCanonical(
916 \\const e = f;916// \\fn foo(ptr: [*]u8) void {}
917 \\// zig fmt: on917// \\
918 \\// test1918// );
919 \\/// test2919//}
920 \\const e = f;920//
921 \\921//test "zig fmt: spaces around slice operator" {
922 );922// try testCanonical(
923}923// \\var a = b[c..d];
924924// \\var a = b[c..d :0];
925test "zig fmt: doc and line comment following 'zig fmt: on'" {925// \\var a = b[c + 1 .. d];
926 try testCanonical(926// \\var a = b[c + 1 ..];
927 \\// zig fmt: off927// \\var a = b[c .. d + 1];
928 \\const e = f;928// \\var a = b[c .. d + 1 :0];
929 \\// zig fmt: on929// \\var a = b[c.a..d.e];
930 \\/// test1930// \\var a = b[c.a..d.e :0];
931 \\// test2931// \\
932 \\const e = f;932// );
933 \\933//}
934 );934//
935}935//test "zig fmt: async call in if condition" {
936936// try testCanonical(
937test "zig fmt: pointer of unknown length" {937// \\comptime {
938 try testCanonical(938// \\ if (async b()) {
939 \\fn foo(ptr: [*]u8) void {}939// \\ a();
940 \\940// \\ }
941 );941// \\}
942}942// \\
943943// );
944test "zig fmt: spaces around slice operator" {944//}
945 try testCanonical(945//
946 \\var a = b[c..d];946//test "zig fmt: 2nd arg multiline string" {
947 \\var a = b[c..d :0];947// try testCanonical(
948 \\var a = b[c + 1 .. d];948// \\comptime {
949 \\var a = b[c + 1 ..];949// \\ cases.addAsm("hello world linux x86_64",
950 \\var a = b[c .. d + 1];950// \\ \\.text
951 \\var a = b[c .. d + 1 :0];951// \\ , "Hello, world!\n");
952 \\var a = b[c.a..d.e];952// \\}
953 \\var a = b[c.a..d.e :0];953// \\
954 \\954// );
955 );955//}
956}956//
957957//test "zig fmt: 2nd arg multiline string many args" {
958test "zig fmt: async call in if condition" {958// try testCanonical(
959 try testCanonical(959// \\comptime {
960 \\comptime {960// \\ cases.addAsm("hello world linux x86_64",
961 \\ if (async b()) {961// \\ \\.text
962 \\ a();962// \\ , "Hello, world!\n", "Hello, world!\n");
963 \\ }963// \\}
964 \\}964// \\
965 \\965// );
966 );966//}
967}967//
968968//test "zig fmt: final arg multiline string" {
969test "zig fmt: 2nd arg multiline string" {969// try testCanonical(
970 try testCanonical(970// \\comptime {
971 \\comptime {971// \\ cases.addAsm("hello world linux x86_64", "Hello, world!\n",
972 \\ cases.addAsm("hello world linux x86_64",972// \\ \\.text
973 \\ \\.text973// \\ );
974 \\ , "Hello, world!\n");974// \\}
975 \\}975// \\
976 \\976// );
977 );977//}
978}978//
979979//test "zig fmt: if condition wraps" {
980test "zig fmt: 2nd arg multiline string many args" {980// try testTransform(
981 try testCanonical(981// \\comptime {
982 \\comptime {982// \\ if (cond and
983 \\ cases.addAsm("hello world linux x86_64",983// \\ cond) {
984 \\ \\.text984// \\ return x;
985 \\ , "Hello, world!\n", "Hello, world!\n");985// \\ }
986 \\}986// \\ while (cond and
987 \\987// \\ cond) {
988 );988// \\ return x;
989}989// \\ }
990990// \\ if (a == b and
991test "zig fmt: final arg multiline string" {991// \\ c) {
992 try testCanonical(992// \\ a = b;
993 \\comptime {993// \\ }
994 \\ cases.addAsm("hello world linux x86_64", "Hello, world!\n",994// \\ while (a == b and
995 \\ \\.text995// \\ c) {
996 \\ );996// \\ a = b;
997 \\}997// \\ }
998 \\998// \\ if ((cond and
999 );999// \\ cond)) {
1000}1000// \\ return x;
10011001// \\ }
1002test "zig fmt: if condition wraps" {1002// \\ while ((cond and
1003 try testTransform(1003// \\ cond)) {
1004 \\comptime {1004// \\ return x;
1005 \\ if (cond and1005// \\ }
1006 \\ cond) {1006// \\ var a = if (a) |*f| x: {
1007 \\ return x;1007// \\ break :x &a.b;
1008 \\ }1008// \\ } else |err| err;
1009 \\ while (cond and1009// \\ var a = if (cond and
1010 \\ cond) {1010// \\ cond) |*f|
1011 \\ return x;1011// \\ x: {
1012 \\ }1012// \\ break :x &a.b;
1013 \\ if (a == b and1013// \\ } else |err| err;
1014 \\ c) {1014// \\}
1015 \\ a = b;1015// ,
1016 \\ }1016// \\comptime {
1017 \\ while (a == b and1017// \\ if (cond and
1018 \\ c) {1018// \\ cond)
1019 \\ a = b;1019// \\ {
1020 \\ }1020// \\ return x;
1021 \\ if ((cond and1021// \\ }
1022 \\ cond)) {1022// \\ while (cond and
1023 \\ return x;1023// \\ cond)
1024 \\ }1024// \\ {
1025 \\ while ((cond and1025// \\ return x;
1026 \\ cond)) {1026// \\ }
1027 \\ return x;1027// \\ if (a == b and
1028 \\ }1028// \\ c)
1029 \\ var a = if (a) |*f| x: {1029// \\ {
1030 \\ break :x &a.b;1030// \\ a = b;
1031 \\ } else |err| err;1031// \\ }
1032 \\ var a = if (cond and1032// \\ while (a == b and
1033 \\ cond) |*f|1033// \\ c)
1034 \\ x: {1034// \\ {
1035 \\ break :x &a.b;1035// \\ a = b;
1036 \\ } else |err| err;1036// \\ }
1037 \\}1037// \\ if ((cond and
1038 ,1038// \\ cond))
1039 \\comptime {1039// \\ {
1040 \\ if (cond and1040// \\ return x;
1041 \\ cond)1041// \\ }
1042 \\ {1042// \\ while ((cond and
1043 \\ return x;1043// \\ cond))
1044 \\ }1044// \\ {
1045 \\ while (cond and1045// \\ return x;
1046 \\ cond)1046// \\ }
1047 \\ {1047// \\ var a = if (a) |*f| x: {
1048 \\ return x;1048// \\ break :x &a.b;
1049 \\ }1049// \\ } else |err| err;
1050 \\ if (a == b and1050// \\ var a = if (cond and
1051 \\ c)1051// \\ cond) |*f|
1052 \\ {1052// \\ x: {
1053 \\ a = b;1053// \\ break :x &a.b;
1054 \\ }1054// \\ } else |err| err;
1055 \\ while (a == b and1055// \\}
1056 \\ c)1056// \\
1057 \\ {1057// );
1058 \\ a = b;1058//}
1059 \\ }1059//
1060 \\ if ((cond and1060//test "zig fmt: if condition has line break but must not wrap" {
1061 \\ cond))1061// try testCanonical(
1062 \\ {1062// \\comptime {
1063 \\ return x;1063// \\ if (self.user_input_options.put(
1064 \\ }1064// \\ name,
1065 \\ while ((cond and1065// \\ UserInputOption{
1066 \\ cond))1066// \\ .name = name,
1067 \\ {1067// \\ .used = false,
1068 \\ return x;1068// \\ },
1069 \\ }1069// \\ ) catch unreachable) |*prev_value| {
1070 \\ var a = if (a) |*f| x: {1070// \\ foo();
1071 \\ break :x &a.b;1071// \\ bar();
1072 \\ } else |err| err;1072// \\ }
1073 \\ var a = if (cond and1073// \\ if (put(
1074 \\ cond) |*f|1074// \\ a,
1075 \\ x: {1075// \\ b,
1076 \\ break :x &a.b;1076// \\ )) {
1077 \\ } else |err| err;1077// \\ foo();
1078 \\}1078// \\ }
1079 \\1079// \\}
1080 );1080// \\
1081}1081// );
10821082//}
1083test "zig fmt: if condition has line break but must not wrap" {1083//
1084 try testCanonical(1084//test "zig fmt: if condition has line break but must not wrap" {
1085 \\comptime {1085// try testCanonical(
1086 \\ if (self.user_input_options.put(1086// \\comptime {
1087 \\ name,1087// \\ if (self.user_input_options.put(name, UserInputOption{
1088 \\ UserInputOption{1088// \\ .name = name,
1089 \\ .name = name,1089// \\ .used = false,
1090 \\ .used = false,1090// \\ }) catch unreachable) |*prev_value| {
1091 \\ },1091// \\ foo();
1092 \\ ) catch unreachable) |*prev_value| {1092// \\ bar();
1093 \\ foo();1093// \\ }
1094 \\ bar();1094// \\ if (put(
1095 \\ }1095// \\ a,
1096 \\ if (put(1096// \\ b,
1097 \\ a,1097// \\ )) {
1098 \\ b,1098// \\ foo();
1099 \\ )) {1099// \\ }
1100 \\ foo();1100// \\}
1101 \\ }1101// \\
1102 \\}1102// );
1103 \\1103//}
1104 );1104//
1105}1105//test "zig fmt: function call with multiline argument" {
11061106// try testCanonical(
1107test "zig fmt: if condition has line break but must not wrap" {1107// \\comptime {
1108 try testCanonical(1108// \\ self.user_input_options.put(name, UserInputOption{
1109 \\comptime {1109// \\ .name = name,
1110 \\ if (self.user_input_options.put(name, UserInputOption{1110// \\ .used = false,
1111 \\ .name = name,1111// \\ });
1112 \\ .used = false,1112// \\}
1113 \\ }) catch unreachable) |*prev_value| {1113// \\
1114 \\ foo();1114// );
1115 \\ bar();1115//}
1116 \\ }1116//
1117 \\ if (put(1117//test "zig fmt: same-line doc comment on variable declaration" {
1118 \\ a,1118// try testTransform(
1119 \\ b,1119// \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
1120 \\ )) {1120// \\pub const MAP_FILE = 0x0000; /// map from file (default)
1121 \\ foo();1121// \\
1122 \\ }1122// \\pub const EMEDIUMTYPE = 124; /// Wrong medium type
1123 \\}1123// \\
1124 \\1124// \\// nameserver query return codes
1125 );1125// \\pub const ENSROK = 0; /// DNS server returned answer with no data
1126}1126// ,
11271127// \\/// allocated from memory, swap space
1128test "zig fmt: function call with multiline argument" {1128// \\pub const MAP_ANONYMOUS = 0x1000;
1129 try testCanonical(1129// \\/// map from file (default)
1130 \\comptime {1130// \\pub const MAP_FILE = 0x0000;
1131 \\ self.user_input_options.put(name, UserInputOption{1131// \\
1132 \\ .name = name,1132// \\/// Wrong medium type
1133 \\ .used = false,1133// \\pub const EMEDIUMTYPE = 124;
1134 \\ });1134// \\
1135 \\}1135// \\// nameserver query return codes
1136 \\1136// \\/// DNS server returned answer with no data
1137 );1137// \\pub const ENSROK = 0;
1138}1138// \\
11391139// );
1140test "zig fmt: same-line doc comment on variable declaration" {1140//}
1141 try testTransform(1141//
1142 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space1142//test "zig fmt: if-else with comment before else" {
1143 \\pub const MAP_FILE = 0x0000; /// map from file (default)1143// try testCanonical(
1144 \\1144// \\comptime {
1145 \\pub const EMEDIUMTYPE = 124; /// Wrong medium type1145// \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
1146 \\1146// \\ if ((hx & 0x7fffffff) != 0x7f800000) {
1147 \\// nameserver query return codes1147// \\ return Complex(f32).new(y - y, y - y);
1148 \\pub const ENSROK = 0; /// DNS server returned answer with no data1148// \\ } // cexp(-inf +- i inf|nan) = 0 + i0
1149 ,1149// \\ else if (hx & 0x80000000 != 0) {
1150 \\/// allocated from memory, swap space1150// \\ return Complex(f32).new(0, 0);
1151 \\pub const MAP_ANONYMOUS = 0x1000;1151// \\ } // cexp(+inf +- i inf|nan) = inf + i nan
1152 \\/// map from file (default)1152// \\ else {
1153 \\pub const MAP_FILE = 0x0000;1153// \\ return Complex(f32).new(x, y - y);
1154 \\1154// \\ }
1155 \\/// Wrong medium type1155// \\}
1156 \\pub const EMEDIUMTYPE = 124;1156// \\
1157 \\1157// );
1158 \\// nameserver query return codes1158//}
1159 \\/// DNS server returned answer with no data1159//
1160 \\pub const ENSROK = 0;1160//test "zig fmt: if nested" {
1161 \\1161// try testCanonical(
1162 );1162// \\pub fn foo() void {
1163}1163// \\ return if ((aInt & bInt) >= 0)
11641164// \\ if (aInt < bInt)
1165test "zig fmt: if-else with comment before else" {1165// \\ GE_LESS
1166 try testCanonical(1166// \\ else if (aInt == bInt)
1167 \\comptime {1167// \\ GE_EQUAL
1168 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan1168// \\ else
1169 \\ if ((hx & 0x7fffffff) != 0x7f800000) {1169// \\ GE_GREATER
1170 \\ return Complex(f32).new(y - y, y - y);1170// \\ else if (aInt > bInt)
1171 \\ } // cexp(-inf +- i inf|nan) = 0 + i01171// \\ GE_LESS
1172 \\ else if (hx & 0x80000000 != 0) {1172// \\ else if (aInt == bInt)
1173 \\ return Complex(f32).new(0, 0);1173// \\ GE_EQUAL
1174 \\ } // cexp(+inf +- i inf|nan) = inf + i nan1174// \\ else
1175 \\ else {1175// \\ GE_GREATER;
1176 \\ return Complex(f32).new(x, y - y);1176// \\}
1177 \\ }1177// \\
1178 \\}1178// );
1179 \\1179//}
1180 );1180//
1181}1181//test "zig fmt: respect line breaks in if-else" {
11821182// try testCanonical(
1183test "zig fmt: if nested" {1183// \\comptime {
1184 try testCanonical(1184// \\ return if (cond) a else b;
1185 \\pub fn foo() void {1185// \\ return if (cond)
1186 \\ return if ((aInt & bInt) >= 0)1186// \\ a
1187 \\ if (aInt < bInt)1187// \\ else
1188 \\ GE_LESS1188// \\ b;
1189 \\ else if (aInt == bInt)1189// \\ return if (cond)
1190 \\ GE_EQUAL1190// \\ a
1191 \\ else1191// \\ else if (cond)
1192 \\ GE_GREATER1192// \\ b
1193 \\ else if (aInt > bInt)1193// \\ else
1194 \\ GE_LESS1194// \\ c;
1195 \\ else if (aInt == bInt)1195// \\}
1196 \\ GE_EQUAL1196// \\
1197 \\ else1197// );
1198 \\ GE_GREATER;1198//}
1199 \\}1199//
1200 \\1200//test "zig fmt: respect line breaks after infix operators" {
1201 );1201// try testCanonical(
1202}1202// \\comptime {
12031203// \\ self.crc =
1204test "zig fmt: respect line breaks in if-else" {1204// \\ lookup_tables[0][p[7]] ^
1205 try testCanonical(1205// \\ lookup_tables[1][p[6]] ^
1206 \\comptime {1206// \\ lookup_tables[2][p[5]] ^
1207 \\ return if (cond) a else b;1207// \\ lookup_tables[3][p[4]] ^
1208 \\ return if (cond)1208// \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
1209 \\ a1209// \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
1210 \\ else1210// \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
1211 \\ b;1211// \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];
1212 \\ return if (cond)1212// \\}
1213 \\ a1213// \\
1214 \\ else if (cond)1214// );
1215 \\ b1215//}
1216 \\ else1216//
1217 \\ c;1217//test "zig fmt: fn decl with trailing comma" {
1218 \\}1218// try testTransform(
1219 \\1219// \\fn foo(a: i32, b: i32,) void {}
1220 );1220// ,
1221}1221// \\fn foo(
12221222// \\ a: i32,
1223test "zig fmt: respect line breaks after infix operators" {1223// \\ b: i32,
1224 try testCanonical(1224// \\) void {}
1225 \\comptime {1225// \\
1226 \\ self.crc =1226// );
1227 \\ lookup_tables[0][p[7]] ^1227//}
1228 \\ lookup_tables[1][p[6]] ^1228//
1229 \\ lookup_tables[2][p[5]] ^1229//test "zig fmt: enum decl with no trailing comma" {
1230 \\ lookup_tables[3][p[4]] ^1230// try testTransform(
1231 \\ lookup_tables[4][@truncate(u8, self.crc >> 24)] ^1231// \\const StrLitKind = enum {Normal, C};
1232 \\ lookup_tables[5][@truncate(u8, self.crc >> 16)] ^1232// ,
1233 \\ lookup_tables[6][@truncate(u8, self.crc >> 8)] ^1233// \\const StrLitKind = enum { Normal, C };
1234 \\ lookup_tables[7][@truncate(u8, self.crc >> 0)];1234// \\
1235 \\}1235// );
1236 \\1236//}
1237 );1237//
1238}1238//test "zig fmt: switch comment before prong" {
12391239// try testCanonical(
1240test "zig fmt: fn decl with trailing comma" {1240// \\comptime {
1241 try testTransform(1241// \\ switch (a) {
1242 \\fn foo(a: i32, b: i32,) void {}1242// \\ // hi
1243 ,1243// \\ 0 => {},
1244 \\fn foo(1244// \\ }
1245 \\ a: i32,1245// \\}
1246 \\ b: i32,1246// \\
1247 \\) void {}1247// );
1248 \\1248//}
1249 );1249//
1250}1250//test "zig fmt: struct literal no trailing comma" {
12511251// try testTransform(
1252test "zig fmt: enum decl with no trailing comma" {1252// \\const a = foo{ .x = 1, .y = 2 };
1253 try testTransform(1253// \\const a = foo{ .x = 1,
1254 \\const StrLitKind = enum {Normal, C};1254// \\ .y = 2 };
1255 ,1255// ,
1256 \\const StrLitKind = enum { Normal, C };1256// \\const a = foo{ .x = 1, .y = 2 };
1257 \\1257// \\const a = foo{
1258 );1258// \\ .x = 1,
1259}1259// \\ .y = 2,
12601260// \\};
1261test "zig fmt: switch comment before prong" {1261// \\
1262 try testCanonical(1262// );
1263 \\comptime {1263//}
1264 \\ switch (a) {1264//
1265 \\ // hi1265//test "zig fmt: struct literal containing a multiline expression" {
1266 \\ 0 => {},1266// try testTransform(
1267 \\ }1267// \\const a = A{ .x = if (f1()) 10 else 20 };
1268 \\}1268// \\const a = A{ .x = if (f1()) 10 else 20, };
1269 \\1269// \\const a = A{ .x = if (f1())
1270 );1270// \\ 10 else 20 };
1271}1271// \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
12721272// \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100, };
1273test "zig fmt: struct literal no trailing comma" {1273// \\const a = A{ .x = if (f1())
1274 try testTransform(1274// \\ 10 else 20};
1275 \\const a = foo{ .x = 1, .y = 2 };1275// \\const a = A{ .x = switch(g) {0 => "ok", else => "no"} };
1276 \\const a = foo{ .x = 1,1276// \\
1277 \\ .y = 2 };1277// ,
1278 ,1278// \\const a = A{ .x = if (f1()) 10 else 20 };
1279 \\const a = foo{ .x = 1, .y = 2 };1279// \\const a = A{
1280 \\const a = foo{1280// \\ .x = if (f1()) 10 else 20,
1281 \\ .x = 1,1281// \\};
1282 \\ .y = 2,1282// \\const a = A{
1283 \\};1283// \\ .x = if (f1())
1284 \\1284// \\ 10
1285 );1285// \\ else
1286}1286// \\ 20,
12871287// \\};
1288test "zig fmt: struct literal containing a multiline expression" {1288// \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
1289 try testTransform(1289// \\const a = A{
1290 \\const a = A{ .x = if (f1()) 10 else 20 };1290// \\ .x = if (f1()) 10 else 20,
1291 \\const a = A{ .x = if (f1()) 10 else 20, };1291// \\ .y = f2() + 100,
1292 \\const a = A{ .x = if (f1())1292// \\};
1293 \\ 10 else 20 };1293// \\const a = A{
1294 \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };1294// \\ .x = if (f1())
1295 \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100, };1295// \\ 10
1296 \\const a = A{ .x = if (f1())1296// \\ else
1297 \\ 10 else 20};1297// \\ 20,
1298 \\const a = A{ .x = switch(g) {0 => "ok", else => "no"} };1298// \\};
1299 \\1299// \\const a = A{
1300 ,1300// \\ .x = switch (g) {
1301 \\const a = A{ .x = if (f1()) 10 else 20 };1301// \\ 0 => "ok",
1302 \\const a = A{1302// \\ else => "no",
1303 \\ .x = if (f1()) 10 else 20,1303// \\ },
1304 \\};1304// \\};
1305 \\const a = A{1305// \\
1306 \\ .x = if (f1())1306// );
1307 \\ 101307//}
1308 \\ else1308//
1309 \\ 20,1309//test "zig fmt: array literal with hint" {
1310 \\};1310// try testTransform(
1311 \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };1311// \\const a = []u8{
1312 \\const a = A{1312// \\ 1, 2, //
1313 \\ .x = if (f1()) 10 else 20,1313// \\ 3,
1314 \\ .y = f2() + 100,1314// \\ 4,
1315 \\};1315// \\ 5,
1316 \\const a = A{1316// \\ 6,
1317 \\ .x = if (f1())1317// \\ 7 };
1318 \\ 101318// \\const a = []u8{
1319 \\ else1319// \\ 1, 2, //
1320 \\ 20,1320// \\ 3,
1321 \\};1321// \\ 4,
1322 \\const a = A{1322// \\ 5,
1323 \\ .x = switch (g) {1323// \\ 6,
1324 \\ 0 => "ok",1324// \\ 7, 8 };
1325 \\ else => "no",1325// \\const a = []u8{
1326 \\ },1326// \\ 1, 2, //
1327 \\};1327// \\ 3,
1328 \\1328// \\ 4,
1329 );1329// \\ 5,
1330}1330// \\ 6, // blah
13311331// \\ 7, 8 };
1332test "zig fmt: array literal with hint" {1332// \\const a = []u8{
1333 try testTransform(1333// \\ 1, 2, //
1334 \\const a = []u8{1334// \\ 3, //
1335 \\ 1, 2, //1335// \\ 4,
1336 \\ 3,1336// \\ 5,
1337 \\ 4,1337// \\ 6,
1338 \\ 5,1338// \\ 7 };
1339 \\ 6,1339// \\const a = []u8{
1340 \\ 7 };1340// \\ 1,
1341 \\const a = []u8{1341// \\ 2,
1342 \\ 1, 2, //1342// \\ 3, 4, //
1343 \\ 3,1343// \\ 5, 6, //
1344 \\ 4,1344// \\ 7, 8, //
1345 \\ 5,1345// \\};
1346 \\ 6,1346// ,
1347 \\ 7, 8 };1347// \\const a = []u8{
1348 \\const a = []u8{1348// \\ 1, 2,
1349 \\ 1, 2, //1349// \\ 3, 4,
1350 \\ 3,1350// \\ 5, 6,
1351 \\ 4,1351// \\ 7,
1352 \\ 5,1352// \\};
1353 \\ 6, // blah1353// \\const a = []u8{
1354 \\ 7, 8 };1354// \\ 1, 2,
1355 \\const a = []u8{1355// \\ 3, 4,
1356 \\ 1, 2, //1356// \\ 5, 6,
1357 \\ 3, //1357// \\ 7, 8,
1358 \\ 4,1358// \\};
1359 \\ 5,1359// \\const a = []u8{
1360 \\ 6,1360// \\ 1, 2,
1361 \\ 7 };1361// \\ 3, 4,
1362 \\const a = []u8{1362// \\ 5,
1363 \\ 1,1363// \\ 6, // blah
1364 \\ 2,1364// \\ 7,
1365 \\ 3, 4, //1365// \\ 8,
1366 \\ 5, 6, //1366// \\};
1367 \\ 7, 8, //1367// \\const a = []u8{
1368 \\};1368// \\ 1, 2,
1369 ,1369// \\ 3, //
1370 \\const a = []u8{1370// \\ 4,
1371 \\ 1, 2,1371// \\ 5, 6,
1372 \\ 3, 4,1372// \\ 7,
1373 \\ 5, 6,1373// \\};
1374 \\ 7,1374// \\const a = []u8{
1375 \\};1375// \\ 1,
1376 \\const a = []u8{1376// \\ 2,
1377 \\ 1, 2,1377// \\ 3,
1378 \\ 3, 4,1378// \\ 4,
1379 \\ 5, 6,1379// \\ 5,
1380 \\ 7, 8,1380// \\ 6,
1381 \\};1381// \\ 7,
1382 \\const a = []u8{1382// \\ 8,
1383 \\ 1, 2,1383// \\};
1384 \\ 3, 4,1384// \\
1385 \\ 5,1385// );
1386 \\ 6, // blah1386//}
1387 \\ 7,1387//
1388 \\ 8,1388//test "zig fmt: array literal veritical column alignment" {
1389 \\};1389// try testTransform(
1390 \\const a = []u8{1390// \\const a = []u8{
1391 \\ 1, 2,1391// \\ 1000, 200,
1392 \\ 3, //1392// \\ 30, 4,
1393 \\ 4,1393// \\ 50000, 60
1394 \\ 5, 6,1394// \\};
1395 \\ 7,1395// \\const a = []u8{0, 1, 2, 3, 40,
1396 \\};1396// \\ 4,5,600,7,
1397 \\const a = []u8{1397// \\ 80,
1398 \\ 1,1398// \\ 9, 10, 11, 0, 13, 14, 15};
1399 \\ 2,1399// \\
1400 \\ 3,1400// ,
1401 \\ 4,1401// \\const a = []u8{
1402 \\ 5,1402// \\ 1000, 200,
1403 \\ 6,1403// \\ 30, 4,
1404 \\ 7,1404// \\ 50000, 60,
1405 \\ 8,1405// \\};
1406 \\};1406// \\const a = []u8{
1407 \\1407// \\ 0, 1, 2, 3, 40,
1408 );1408// \\ 4, 5, 600, 7, 80,
1409}1409// \\ 9, 10, 11, 0, 13,
14101410// \\ 14, 15,
1411test "zig fmt: array literal veritical column alignment" {1411// \\};
1412 try testTransform(1412// \\
1413 \\const a = []u8{1413// );
1414 \\ 1000, 200,1414//}
1415 \\ 30, 4,1415//
1416 \\ 50000, 601416//test "zig fmt: multiline string with backslash at end of line" {
1417 \\};1417// try testCanonical(
1418 \\const a = []u8{0, 1, 2, 3, 40,1418// \\comptime {
1419 \\ 4,5,600,7,1419// \\ err(
1420 \\ 80,1420// \\ \\\
1421 \\ 9, 10, 11, 0, 13, 14, 15};1421// \\ );
1422 \\1422// \\}
1423 ,1423// \\
1424 \\const a = []u8{1424// );
1425 \\ 1000, 200,1425//}
1426 \\ 30, 4,1426//
1427 \\ 50000, 60,1427//test "zig fmt: multiline string parameter in fn call with trailing comma" {
1428 \\};1428// try testCanonical(
1429 \\const a = []u8{1429// \\fn foo() void {
1430 \\ 0, 1, 2, 3, 40,1430// \\ try stdout.print(
1431 \\ 4, 5, 600, 7, 80,1431// \\ \\ZIG_CMAKE_BINARY_DIR {}
1432 \\ 9, 10, 11, 0, 13,1432// \\ \\ZIG_C_HEADER_FILES {}
1433 \\ 14, 15,1433// \\ \\ZIG_DIA_GUIDS_LIB {}
1434 \\};1434// \\ \\
1435 \\1435// \\ ,
1436 );1436// \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
1437}1437// \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
14381438// \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
1439test "zig fmt: multiline string with backslash at end of line" {1439// \\ );
1440 try testCanonical(1440// \\}
1441 \\comptime {1441// \\
1442 \\ err(1442// );
1443 \\ \\\1443//}
1444 \\ );1444//
1445 \\}1445//test "zig fmt: trailing comma on fn call" {
1446 \\1446// try testCanonical(
1447 );1447// \\comptime {
1448}1448// \\ var module = try Module.create(
14491449// \\ allocator,
1450test "zig fmt: multiline string parameter in fn call with trailing comma" {1450// \\ zig_lib_dir,
1451 try testCanonical(1451// \\ full_cache_dir,
1452 \\fn foo() void {1452// \\ );
1453 \\ try stdout.print(1453// \\}
1454 \\ \\ZIG_CMAKE_BINARY_DIR {}1454// \\
1455 \\ \\ZIG_C_HEADER_FILES {}1455// );
1456 \\ \\ZIG_DIA_GUIDS_LIB {}1456//}
1457 \\ \\1457//
1458 \\ ,1458//test "zig fmt: multi line arguments without last comma" {
1459 \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),1459// try testTransform(
1460 \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),1460// \\pub fn foo(
1461 \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),1461// \\ a: usize,
1462 \\ );1462// \\ b: usize,
1463 \\}1463// \\ c: usize,
1464 \\1464// \\ d: usize
1465 );1465// \\) usize {
1466}1466// \\ return a + b + c + d;
14671467// \\}
1468test "zig fmt: trailing comma on fn call" {1468// \\
1469 try testCanonical(1469// ,
1470 \\comptime {1470// \\pub fn foo(a: usize, b: usize, c: usize, d: usize) usize {
1471 \\ var module = try Module.create(1471// \\ return a + b + c + d;
1472 \\ allocator,1472// \\}
1473 \\ zig_lib_dir,1473// \\
1474 \\ full_cache_dir,1474// );
1475 \\ );1475//}
1476 \\}1476//
1477 \\1477//test "zig fmt: empty block with only comment" {
1478 );1478// try testCanonical(
1479}1479// \\comptime {
14801480// \\ {
1481test "zig fmt: multi line arguments without last comma" {1481// \\ // comment
1482 try testTransform(1482// \\ }
1483 \\pub fn foo(1483// \\}
1484 \\ a: usize,1484// \\
1485 \\ b: usize,1485// );
1486 \\ c: usize,1486//}
1487 \\ d: usize1487//
1488 \\) usize {1488//test "zig fmt: no trailing comma on struct decl" {
1489 \\ return a + b + c + d;1489// try testCanonical(
1490 \\}1490// \\const RoundParam = struct {
1491 \\1491// \\ k: usize, s: u32, t: u32
1492 ,1492// \\};
1493 \\pub fn foo(a: usize, b: usize, c: usize, d: usize) usize {1493// \\
1494 \\ return a + b + c + d;1494// );
1495 \\}1495//}
1496 \\1496//
1497 );1497//test "zig fmt: extra newlines at the end" {
1498}1498// try testTransform(
14991499// \\const a = b;
1500test "zig fmt: empty block with only comment" {1500// \\
1501 try testCanonical(1501// \\
1502 \\comptime {1502// \\
1503 \\ {1503// ,
1504 \\ // comment1504// \\const a = b;
1505 \\ }1505// \\
1506 \\}1506// );
1507 \\1507//}
1508 );1508//
1509}1509//test "zig fmt: simple asm" {
15101510// try testTransform(
1511test "zig fmt: no trailing comma on struct decl" {1511// \\comptime {
1512 try testCanonical(1512// \\ asm volatile (
1513 \\const RoundParam = struct {1513// \\ \\.globl aoeu;
1514 \\ k: usize, s: u32, t: u321514// \\ \\.type aoeu, @function;
1515 \\};1515// \\ \\.set aoeu, derp;
1516 \\1516// \\ );
1517 );1517// \\
1518}1518// \\ asm ("not real assembly"
15191519// \\ :[a] "x" (x),);
1520test "zig fmt: extra newlines at the end" {1520// \\ asm ("not real assembly"
1521 try testTransform(1521// \\ :[a] "x" (->i32),:[a] "x" (1),);
1522 \\const a = b;1522// \\ asm ("still not real assembly"
1523 \\1523// \\ :::"a","b",);
1524 \\1524// \\}
1525 \\1525// ,
1526 ,1526// \\comptime {
1527 \\const a = b;1527// \\ asm volatile (
1528 \\1528// \\ \\.globl aoeu;
1529 );1529// \\ \\.type aoeu, @function;
1530}1530// \\ \\.set aoeu, derp;
15311531// \\ );
1532test "zig fmt: simple asm" {1532// \\
1533 try testTransform(1533// \\ asm ("not real assembly"
1534 \\comptime {1534// \\ : [a] "x" (x)
1535 \\ asm volatile (1535// \\ );
1536 \\ \\.globl aoeu;1536// \\ asm ("not real assembly"
1537 \\ \\.type aoeu, @function;1537// \\ : [a] "x" (-> i32)
1538 \\ \\.set aoeu, derp;1538// \\ : [a] "x" (1)
1539 \\ );1539// \\ );
1540 \\1540// \\ asm ("still not real assembly"
1541 \\ asm ("not real assembly"1541// \\ :
1542 \\ :[a] "x" (x),);1542// \\ :
1543 \\ asm ("not real assembly"1543// \\ : "a", "b"
1544 \\ :[a] "x" (->i32),:[a] "x" (1),);1544// \\ );
1545 \\ asm ("still not real assembly"1545// \\}
1546 \\ :::"a","b",);1546// \\
1547 \\}1547// );
1548 ,1548//}
1549 \\comptime {1549//
1550 \\ asm volatile (1550//test "zig fmt: nested struct literal with one item" {
1551 \\ \\.globl aoeu;1551// try testCanonical(
1552 \\ \\.type aoeu, @function;1552// \\const a = foo{
1553 \\ \\.set aoeu, derp;1553// \\ .item = bar{ .a = b },
1554 \\ );1554// \\};
1555 \\1555// \\
1556 \\ asm ("not real assembly"1556// );
1557 \\ : [a] "x" (x)1557//}
1558 \\ );1558//
1559 \\ asm ("not real assembly"1559//test "zig fmt: switch cases trailing comma" {
1560 \\ : [a] "x" (-> i32)1560// try testTransform(
1561 \\ : [a] "x" (1)1561// \\fn switch_cases(x: i32) void {
1562 \\ );1562// \\ switch (x) {
1563 \\ asm ("still not real assembly"1563// \\ 1,2,3 => {},
1564 \\ :1564// \\ 4,5, => {},
1565 \\ :1565// \\ 6... 8, => {},
1566 \\ : "a", "b"1566// \\ else => {},
1567 \\ );1567// \\ }
1568 \\}1568// \\}
1569 \\1569// ,
1570 );1570// \\fn switch_cases(x: i32) void {
1571}1571// \\ switch (x) {
15721572// \\ 1, 2, 3 => {},
1573test "zig fmt: nested struct literal with one item" {1573// \\ 4,
1574 try testCanonical(1574// \\ 5,
1575 \\const a = foo{1575// \\ => {},
1576 \\ .item = bar{ .a = b },1576// \\ 6...8 => {},
1577 \\};1577// \\ else => {},
1578 \\1578// \\ }
1579 );1579// \\}
1580}1580// \\
15811581// );
1582test "zig fmt: switch cases trailing comma" {1582//}
1583 try testTransform(1583//
1584 \\fn switch_cases(x: i32) void {1584//test "zig fmt: slice align" {
1585 \\ switch (x) {1585// try testCanonical(
1586 \\ 1,2,3 => {},1586// \\const A = struct {
1587 \\ 4,5, => {},1587// \\ items: []align(A) T,
1588 \\ 6... 8, => {},1588// \\};
1589 \\ else => {},1589// \\
1590 \\ }1590// );
1591 \\}1591//}
1592 ,1592//
1593 \\fn switch_cases(x: i32) void {1593//test "zig fmt: add trailing comma to array literal" {
1594 \\ switch (x) {1594// try testTransform(
1595 \\ 1, 2, 3 => {},1595// \\comptime {
1596 \\ 4,1596// \\ return []u16{'m', 's', 'y', 's', '-' // hi
1597 \\ 5,1597// \\ };
1598 \\ => {},1598// \\ return []u16{'m', 's', 'y', 's',
1599 \\ 6...8 => {},1599// \\ '-'};
1600 \\ else => {},1600// \\ return []u16{'m', 's', 'y', 's', '-'};
1601 \\ }1601// \\}
1602 \\}1602// ,
1603 \\1603// \\comptime {
1604 );1604// \\ return []u16{
1605}1605// \\ 'm', 's', 'y', 's', '-', // hi
16061606// \\ };
1607test "zig fmt: slice align" {1607// \\ return []u16{
1608 try testCanonical(1608// \\ 'm', 's', 'y', 's',
1609 \\const A = struct {1609// \\ '-',
1610 \\ items: []align(A) T,1610// \\ };
1611 \\};1611// \\ return []u16{ 'm', 's', 'y', 's', '-' };
1612 \\1612// \\}
1613 );1613// \\
1614}1614// );
16151615//}
1616test "zig fmt: add trailing comma to array literal" {1616//
1617 try testTransform(1617//test "zig fmt: first thing in file is line comment" {
1618 \\comptime {1618// try testCanonical(
1619 \\ return []u16{'m', 's', 'y', 's', '-' // hi1619// \\// Introspection and determination of system libraries needed by zig.
1620 \\ };1620// \\
1621 \\ return []u16{'m', 's', 'y', 's',1621// \\// Introspection and determination of system libraries needed by zig.
1622 \\ '-'};1622// \\
1623 \\ return []u16{'m', 's', 'y', 's', '-'};1623// \\const std = @import("std");
1624 \\}1624// \\
1625 ,1625// );
1626 \\comptime {1626//}
1627 \\ return []u16{1627//
1628 \\ 'm', 's', 'y', 's', '-', // hi1628//test "zig fmt: line comment after doc comment" {
1629 \\ };1629// try testCanonical(
1630 \\ return []u16{1630// \\/// doc comment
1631 \\ 'm', 's', 'y', 's',1631// \\// line comment
1632 \\ '-',1632// \\fn foo() void {}
1633 \\ };1633// \\
1634 \\ return []u16{ 'm', 's', 'y', 's', '-' };1634// );
1635 \\}1635//}
1636 \\1636//
1637 );1637//test "zig fmt: float literal with exponent" {
1638}1638// try testCanonical(
16391639// \\test "bit field alignment" {
1640test "zig fmt: first thing in file is line comment" {1640// \\ assert(@TypeOf(&blah.b) == *align(1:3:6) const u3);
1641 try testCanonical(1641// \\}
1642 \\// Introspection and determination of system libraries needed by zig.1642// \\
1643 \\1643// );
1644 \\// Introspection and determination of system libraries needed by zig.1644//}
1645 \\1645//
1646 \\const std = @import("std");1646//test "zig fmt: float literal with exponent" {
1647 \\1647// try testCanonical(
1648 );1648// \\test "aoeu" {
1649}1649// \\ switch (state) {
16501650// \\ TermState.Start => switch (c) {
1651test "zig fmt: line comment after doc comment" {1651// \\ '\x1b' => state = TermState.Escape,
1652 try testCanonical(1652// \\ else => try out.writeByte(c),
1653 \\/// doc comment1653// \\ },
1654 \\// line comment1654// \\ }
1655 \\fn foo() void {}1655// \\}
1656 \\1656// \\
1657 );1657// );
1658}1658//}
16591659//test "zig fmt: float literal with exponent" {
1660test "zig fmt: float literal with exponent" {1660// try testCanonical(
1661 try testCanonical(1661// \\pub const f64_true_min = 4.94065645841246544177e-324;
1662 \\test "bit field alignment" {1662// \\const threshold = 0x1.a827999fcef32p+1022;
1663 \\ assert(@TypeOf(&blah.b) == *align(1:3:6) const u3);1663// \\
1664 \\}1664// );
1665 \\1665//}
1666 );1666//
1667}1667//test "zig fmt: if-else end of comptime" {
16681668// try testCanonical(
1669test "zig fmt: float literal with exponent" {1669// \\comptime {
1670 try testCanonical(1670// \\ if (a) {
1671 \\test "aoeu" {1671// \\ b();
1672 \\ switch (state) {1672// \\ } else {
1673 \\ TermState.Start => switch (c) {1673// \\ b();
1674 \\ '\x1b' => state = TermState.Escape,1674// \\ }
1675 \\ else => try out.writeByte(c),1675// \\}
1676 \\ },1676// \\
1677 \\ }1677// );
1678 \\}1678//}
1679 \\1679//
1680 );1680//test "zig fmt: nested blocks" {
1681}1681// try testCanonical(
1682test "zig fmt: float literal with exponent" {1682// \\comptime {
1683 try testCanonical(1683// \\ {
1684 \\pub const f64_true_min = 4.94065645841246544177e-324;1684// \\ {
1685 \\const threshold = 0x1.a827999fcef32p+1022;1685// \\ {
1686 \\1686// \\ a();
1687 );1687// \\ }
1688}1688// \\ }
16891689// \\ }
1690test "zig fmt: if-else end of comptime" {1690// \\}
1691 try testCanonical(1691// \\
1692 \\comptime {1692// );
1693 \\ if (a) {1693//}
1694 \\ b();1694//
1695 \\ } else {1695//test "zig fmt: block with same line comment after end brace" {
1696 \\ b();1696// try testCanonical(
1697 \\ }1697// \\comptime {
1698 \\}1698// \\ {
1699 \\1699// \\ b();
1700 );1700// \\ } // comment
1701}1701// \\}
17021702// \\
1703test "zig fmt: nested blocks" {1703// );
1704 try testCanonical(1704//}
1705 \\comptime {1705//
1706 \\ {1706//test "zig fmt: statements with comment between" {
1707 \\ {1707// try testCanonical(
1708 \\ {1708// \\comptime {
1709 \\ a();1709// \\ a = b;
1710 \\ }1710// \\ // comment
1711 \\ }1711// \\ a = b;
1712 \\ }1712// \\}
1713 \\}1713// \\
1714 \\1714// );
1715 );1715//}
1716}1716//
17171717//test "zig fmt: statements with empty line between" {
1718test "zig fmt: block with same line comment after end brace" {1718// try testCanonical(
1719 try testCanonical(1719// \\comptime {
1720 \\comptime {1720// \\ a = b;
1721 \\ {1721// \\
1722 \\ b();1722// \\ a = b;
1723 \\ } // comment1723// \\}
1724 \\}1724// \\
1725 \\1725// );
1726 );1726//}
1727}1727//
17281728//test "zig fmt: ptr deref operator and unwrap optional operator" {
1729test "zig fmt: statements with comment between" {1729// try testCanonical(
1730 try testCanonical(1730// \\const a = b.*;
1731 \\comptime {1731// \\const a = b.?;
1732 \\ a = b;1732// \\
1733 \\ // comment1733// );
1734 \\ a = b;1734//}
1735 \\}1735//
1736 \\1736//test "zig fmt: comment after if before another if" {
1737 );1737// try testCanonical(
1738}1738// \\test "aoeu" {
17391739// \\ // comment
1740test "zig fmt: statements with empty line between" {1740// \\ if (x) {
1741 try testCanonical(1741// \\ bar();
1742 \\comptime {1742// \\ }
1743 \\ a = b;1743// \\}
1744 \\1744// \\
1745 \\ a = b;1745// \\test "aoeu" {
1746 \\}1746// \\ if (x) {
1747 \\1747// \\ foo();
1748 );1748// \\ }
1749}1749// \\ // comment
17501750// \\ if (x) {
1751test "zig fmt: ptr deref operator and unwrap optional operator" {1751// \\ bar();
1752 try testCanonical(1752// \\ }
1753 \\const a = b.*;1753// \\}
1754 \\const a = b.?;1754// \\
1755 \\1755// );
1756 );1756//}
1757}1757//
17581758//test "zig fmt: line comment between if block and else keyword" {
1759test "zig fmt: comment after if before another if" {1759// try testCanonical(
1760 try testCanonical(1760// \\test "aoeu" {
1761 \\test "aoeu" {1761// \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
1762 \\ // comment1762// \\ if ((hx & 0x7fffffff) != 0x7f800000) {
1763 \\ if (x) {1763// \\ return Complex(f32).new(y - y, y - y);
1764 \\ bar();1764// \\ }
1765 \\ }1765// \\ // cexp(-inf +- i inf|nan) = 0 + i0
1766 \\}1766// \\ else if (hx & 0x80000000 != 0) {
1767 \\1767// \\ return Complex(f32).new(0, 0);
1768 \\test "aoeu" {1768// \\ }
1769 \\ if (x) {1769// \\ // cexp(+inf +- i inf|nan) = inf + i nan
1770 \\ foo();1770// \\ // another comment
1771 \\ }1771// \\ else {
1772 \\ // comment1772// \\ return Complex(f32).new(x, y - y);
1773 \\ if (x) {1773// \\ }
1774 \\ bar();1774// \\}
1775 \\ }1775// \\
1776 \\}1776// );
1777 \\1777//}
1778 );1778//
1779}1779//test "zig fmt: same line comments in expression" {
17801780// try testCanonical(
1781test "zig fmt: line comment between if block and else keyword" {1781// \\test "aoeu" {
1782 try testCanonical(1782// \\ const x = ( // a
1783 \\test "aoeu" {1783// \\ 0 // b
1784 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan1784// \\ ); // c
1785 \\ if ((hx & 0x7fffffff) != 0x7f800000) {1785// \\}
1786 \\ return Complex(f32).new(y - y, y - y);1786// \\
1787 \\ }1787// );
1788 \\ // cexp(-inf +- i inf|nan) = 0 + i01788//}
1789 \\ else if (hx & 0x80000000 != 0) {1789//
1790 \\ return Complex(f32).new(0, 0);1790//test "zig fmt: add comma on last switch prong" {
1791 \\ }1791// try testTransform(
1792 \\ // cexp(+inf +- i inf|nan) = inf + i nan1792// \\test "aoeu" {
1793 \\ // another comment1793// \\switch (self.init_arg_expr) {
1794 \\ else {1794// \\ InitArg.Type => |t| { },
1795 \\ return Complex(f32).new(x, y - y);1795// \\ InitArg.None,
1796 \\ }1796// \\ InitArg.Enum => { }
1797 \\}1797// \\}
1798 \\1798// \\ switch (self.init_arg_expr) {
1799 );1799// \\ InitArg.Type => |t| { },
1800}1800// \\ InitArg.None,
18011801// \\ InitArg.Enum => { }//line comment
1802test "zig fmt: same line comments in expression" {1802// \\ }
1803 try testCanonical(1803// \\}
1804 \\test "aoeu" {1804// ,
1805 \\ const x = ( // a1805// \\test "aoeu" {
1806 \\ 0 // b1806// \\ switch (self.init_arg_expr) {
1807 \\ ); // c1807// \\ InitArg.Type => |t| {},
1808 \\}1808// \\ InitArg.None, InitArg.Enum => {},
1809 \\1809// \\ }
1810 );1810// \\ switch (self.init_arg_expr) {
1811}1811// \\ InitArg.Type => |t| {},
18121812// \\ InitArg.None, InitArg.Enum => {}, //line comment
1813test "zig fmt: add comma on last switch prong" {1813// \\ }
1814 try testTransform(1814// \\}
1815 \\test "aoeu" {1815// \\
1816 \\switch (self.init_arg_expr) {1816// );
1817 \\ InitArg.Type => |t| { },1817//}
1818 \\ InitArg.None,1818//
1819 \\ InitArg.Enum => { }1819//test "zig fmt: same-line comment after a statement" {
1820 \\}1820// try testCanonical(
1821 \\ switch (self.init_arg_expr) {1821// \\test "" {
1822 \\ InitArg.Type => |t| { },1822// \\ a = b;
1823 \\ InitArg.None,1823// \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
1824 \\ InitArg.Enum => { }//line comment1824// \\ a = b;
1825 \\ }1825// \\}
1826 \\}1826// \\
1827 ,1827// );
1828 \\test "aoeu" {1828//}
1829 \\ switch (self.init_arg_expr) {1829//
1830 \\ InitArg.Type => |t| {},1830//test "zig fmt: same-line comment after var decl in struct" {
1831 \\ InitArg.None, InitArg.Enum => {},1831// try testCanonical(
1832 \\ }1832// \\pub const vfs_cap_data = extern struct {
1833 \\ switch (self.init_arg_expr) {1833// \\ const Data = struct {}; // when on disk.
1834 \\ InitArg.Type => |t| {},1834// \\};
1835 \\ InitArg.None, InitArg.Enum => {}, //line comment1835// \\
1836 \\ }1836// );
1837 \\}1837//}
1838 \\1838//
1839 );1839//test "zig fmt: same-line comment after field decl" {
1840}1840// try testCanonical(
18411841// \\pub const dirent = extern struct {
1842test "zig fmt: same-line comment after a statement" {1842// \\ d_name: u8,
1843 try testCanonical(1843// \\ d_name: u8, // comment 1
1844 \\test "" {1844// \\ d_name: u8,
1845 \\ a = b;1845// \\ d_name: u8, // comment 2
1846 \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption1846// \\ d_name: u8,
1847 \\ a = b;1847// \\};
1848 \\}1848// \\
1849 \\1849// );
1850 );1850//}
1851}1851//
18521852//test "zig fmt: same-line comment after switch prong" {
1853test "zig fmt: same-line comment after var decl in struct" {1853// try testCanonical(
1854 try testCanonical(1854// \\test "" {
1855 \\pub const vfs_cap_data = extern struct {1855// \\ switch (err) {
1856 \\ const Data = struct {}; // when on disk.1856// \\ error.PathAlreadyExists => {}, // comment 2
1857 \\};1857// \\ else => return err, // comment 1
1858 \\1858// \\ }
1859 );1859// \\}
1860}1860// \\
18611861// );
1862test "zig fmt: same-line comment after field decl" {1862//}
1863 try testCanonical(1863//
1864 \\pub const dirent = extern struct {1864//test "zig fmt: same-line comment after non-block if expression" {
1865 \\ d_name: u8,1865// try testCanonical(
1866 \\ d_name: u8, // comment 11866// \\comptime {
1867 \\ d_name: u8,1867// \\ if (sr > n_uword_bits - 1) // d > r
1868 \\ d_name: u8, // comment 21868// \\ return 0;
1869 \\ d_name: u8,1869// \\}
1870 \\};1870// \\
1871 \\1871// );
1872 );1872//}
1873}1873//
18741874//test "zig fmt: same-line comment on comptime expression" {
1875test "zig fmt: same-line comment after switch prong" {1875// try testCanonical(
1876 try testCanonical(1876// \\test "" {
1877 \\test "" {1877// \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
1878 \\ switch (err) {1878// \\}
1879 \\ error.PathAlreadyExists => {}, // comment 21879// \\
1880 \\ else => return err, // comment 11880// );
1881 \\ }1881//}
1882 \\}1882//
1883 \\1883//test "zig fmt: switch with empty body" {
1884 );1884// try testCanonical(
1885}1885// \\test "" {
18861886// \\ foo() catch |err| switch (err) {};
1887test "zig fmt: same-line comment after non-block if expression" {1887// \\}
1888 try testCanonical(1888// \\
1889 \\comptime {1889// );
1890 \\ if (sr > n_uword_bits - 1) // d > r1890//}
1891 \\ return 0;1891//
1892 \\}1892//test "zig fmt: line comments in struct initializer" {
1893 \\1893// try testCanonical(
1894 );1894// \\fn foo() void {
1895}1895// \\ return Self{
18961896// \\ .a = b,
1897test "zig fmt: same-line comment on comptime expression" {1897// \\
1898 try testCanonical(1898// \\ // Initialize these two fields to buffer_size so that
1899 \\test "" {1899// \\ // in `readFn` we treat the state as being able to read
1900 \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt1900// \\ .start_index = buffer_size,
1901 \\}1901// \\ .end_index = buffer_size,
1902 \\1902// \\
1903 );1903// \\ // middle
1904}1904// \\
19051905// \\ .a = b,
1906test "zig fmt: switch with empty body" {1906// \\
1907 try testCanonical(1907// \\ // end
1908 \\test "" {1908// \\ };
1909 \\ foo() catch |err| switch (err) {};1909// \\}
1910 \\}1910// \\
1911 \\1911// );
1912 );1912//}
1913}1913//
19141914//test "zig fmt: first line comment in struct initializer" {
1915test "zig fmt: line comments in struct initializer" {1915// try testCanonical(
1916 try testCanonical(1916// \\pub fn acquire(self: *Self) HeldLock {
1917 \\fn foo() void {1917// \\ return HeldLock{
1918 \\ return Self{1918// \\ // guaranteed allocation elision
1919 \\ .a = b,1919// \\ .held = self.lock.acquire(),
1920 \\1920// \\ .value = &self.private_data,
1921 \\ // Initialize these two fields to buffer_size so that1921// \\ };
1922 \\ // in `readFn` we treat the state as being able to read1922// \\}
1923 \\ .start_index = buffer_size,1923// \\
1924 \\ .end_index = buffer_size,1924// );
1925 \\1925//}
1926 \\ // middle1926//
1927 \\1927//test "zig fmt: doc comments before struct field" {
1928 \\ .a = b,1928// try testCanonical(
1929 \\1929// \\pub const Allocator = struct {
1930 \\ // end1930// \\ /// Allocate byte_count bytes and return them in a slice, with the
1931 \\ };1931// \\ /// slice's pointer aligned at least to alignment bytes.
1932 \\}1932// \\ allocFn: fn () void,
1933 \\1933// \\};
1934 );1934// \\
1935}1935// );
19361936//}
1937test "zig fmt: first line comment in struct initializer" {1937//
1938 try testCanonical(1938//test "zig fmt: error set declaration" {
1939 \\pub fn acquire(self: *Self) HeldLock {1939// try testCanonical(
1940 \\ return HeldLock{1940// \\const E = error{
1941 \\ // guaranteed allocation elision1941// \\ A,
1942 \\ .held = self.lock.acquire(),1942// \\ B,
1943 \\ .value = &self.private_data,1943// \\
1944 \\ };1944// \\ C,
1945 \\}1945// \\};
1946 \\1946// \\
1947 );1947// \\const Error = error{
1948}1948// \\ /// no more memory
19491949// \\ OutOfMemory,
1950test "zig fmt: doc comments before struct field" {1950// \\};
1951 try testCanonical(1951// \\
1952 \\pub const Allocator = struct {1952// \\const Error = error{
1953 \\ /// Allocate byte_count bytes and return them in a slice, with the1953// \\ /// no more memory
1954 \\ /// slice's pointer aligned at least to alignment bytes.1954// \\ OutOfMemory,
1955 \\ allocFn: fn () void,1955// \\
1956 \\};1956// \\ /// another
1957 \\1957// \\ Another,
1958 );1958// \\
1959}1959// \\ // end
19601960// \\};
1961test "zig fmt: error set declaration" {1961// \\
1962 try testCanonical(1962// \\const Error = error{OutOfMemory};
1963 \\const E = error{1963// \\const Error = error{};
1964 \\ A,1964// \\
1965 \\ B,1965// \\const Error = error{ OutOfMemory, OutOfTime };
1966 \\1966// \\
1967 \\ C,1967// );
1968 \\};1968//}
1969 \\1969//
1970 \\const Error = error{1970//test "zig fmt: union(enum(u32)) with assigned enum values" {
1971 \\ /// no more memory1971// try testCanonical(
1972 \\ OutOfMemory,1972// \\const MultipleChoice = union(enum(u32)) {
1973 \\};1973// \\ A = 20,
1974 \\1974// \\ B = 40,
1975 \\const Error = error{1975// \\ C = 60,
1976 \\ /// no more memory1976// \\ D = 1000,
1977 \\ OutOfMemory,1977// \\};
1978 \\1978// \\
1979 \\ /// another1979// );
1980 \\ Another,1980//}
1981 \\1981//
1982 \\ // end1982//test "zig fmt: resume from suspend block" {
1983 \\};1983// try testCanonical(
1984 \\1984// \\fn foo() void {
1985 \\const Error = error{OutOfMemory};1985// \\ suspend {
1986 \\const Error = error{};1986// \\ resume @frame();
1987 \\1987// \\ }
1988 \\const Error = error{ OutOfMemory, OutOfTime };1988// \\}
1989 \\1989// \\
1990 );1990// );
1991}1991//}
19921992//
1993test "zig fmt: union(enum(u32)) with assigned enum values" {1993//test "zig fmt: comments before error set decl" {
1994 try testCanonical(1994// try testCanonical(
1995 \\const MultipleChoice = union(enum(u32)) {1995// \\const UnexpectedError = error{
1996 \\ A = 20,1996// \\ /// The Operating System returned an undocumented error code.
1997 \\ B = 40,1997// \\ Unexpected,
1998 \\ C = 60,1998// \\ // another
1999 \\ D = 1000,1999// \\ Another,
2000 \\};2000// \\
2001 \\2001// \\ // in between
2002 );2002// \\
2003}2003// \\ // at end
20042004// \\};
2005test "zig fmt: resume from suspend block" {2005// \\
2006 try testCanonical(2006// );
2007 \\fn foo() void {2007//}
2008 \\ suspend {2008//
2009 \\ resume @frame();2009//test "zig fmt: comments before switch prong" {
2010 \\ }2010// try testCanonical(
2011 \\}2011// \\test "" {
2012 \\2012// \\ switch (err) {
2013 );2013// \\ error.PathAlreadyExists => continue,
2014}2014// \\
20152015// \\ // comment 1
2016test "zig fmt: comments before error set decl" {2016// \\
2017 try testCanonical(2017// \\ // comment 2
2018 \\const UnexpectedError = error{2018// \\ else => return err,
2019 \\ /// The Operating System returned an undocumented error code.2019// \\ // at end
2020 \\ Unexpected,2020// \\ }
2021 \\ // another2021// \\}
2022 \\ Another,2022// \\
2023 \\2023// );
2024 \\ // in between2024//}
2025 \\2025//
2026 \\ // at end2026//test "zig fmt: comments before var decl in struct" {
2027 \\};2027// try testCanonical(
2028 \\2028// \\pub const vfs_cap_data = extern struct {
2029 );2029// \\ // All of these are mandated as little endian
2030}2030// \\ // when on disk.
20312031// \\ const Data = struct {
2032test "zig fmt: comments before switch prong" {2032// \\ permitted: u32,
2033 try testCanonical(2033// \\ inheritable: u32,
2034 \\test "" {2034// \\ };
2035 \\ switch (err) {2035// \\
2036 \\ error.PathAlreadyExists => continue,2036// \\ // in between
2037 \\2037// \\
2038 \\ // comment 12038// \\ /// All of these are mandated as little endian
2039 \\2039// \\ /// when on disk.
2040 \\ // comment 22040// \\ const Data = struct {
2041 \\ else => return err,2041// \\ permitted: u32,
2042 \\ // at end2042// \\ inheritable: u32,
2043 \\ }2043// \\ };
2044 \\}2044// \\
2045 \\2045// \\ // at end
2046 );2046// \\};
2047}2047// \\
20482048// );
2049test "zig fmt: comments before var decl in struct" {2049//}
2050 try testCanonical(2050//
2051 \\pub const vfs_cap_data = extern struct {2051//test "zig fmt: array literal with 1 item on 1 line" {
2052 \\ // All of these are mandated as little endian2052// try testCanonical(
2053 \\ // when on disk.2053// \\var s = []const u64{0} ** 25;
2054 \\ const Data = struct {2054// \\
2055 \\ permitted: u32,2055// );
2056 \\ inheritable: u32,2056//}
2057 \\ };2057//
2058 \\2058//test "zig fmt: comments before global variables" {
2059 \\ // in between2059// try testCanonical(
2060 \\2060// \\/// Foo copies keys and values before they go into the map, and
2061 \\ /// All of these are mandated as little endian2061// \\/// frees them when they get removed.
2062 \\ /// when on disk.2062// \\pub const Foo = struct {};
2063 \\ const Data = struct {2063// \\
2064 \\ permitted: u32,2064// );
2065 \\ inheritable: u32,2065//}
2066 \\ };2066//
2067 \\2067//test "zig fmt: comments in statements" {
2068 \\ // at end2068// try testCanonical(
2069 \\};2069// \\test "std" {
2070 \\2070// \\ // statement comment
2071 );2071// \\ _ = @import("foo/bar.zig");
2072}2072// \\
20732073// \\ // middle
2074test "zig fmt: array literal with 1 item on 1 line" {2074// \\ // middle2
2075 try testCanonical(2075// \\
2076 \\var s = []const u64{0} ** 25;2076// \\ // end
2077 \\2077// \\}
2078 );2078// \\
2079}2079// );
20802080//}
2081test "zig fmt: comments before global variables" {2081//
2082 try testCanonical(2082//test "zig fmt: comments before test decl" {
2083 \\/// Foo copies keys and values before they go into the map, and2083// try testCanonical(
2084 \\/// frees them when they get removed.2084// \\/// top level doc comment
2085 \\pub const Foo = struct {};2085// \\test "hi" {}
2086 \\2086// \\
2087 );2087// \\// top level normal comment
2088}2088// \\test "hi" {}
20892089// \\
2090test "zig fmt: comments in statements" {2090// \\// middle
2091 try testCanonical(2091// \\
2092 \\test "std" {2092// \\// end
2093 \\ // statement comment2093// \\
2094 \\ _ = @import("foo/bar.zig");2094// );
2095 \\2095//}
2096 \\ // middle2096//
2097 \\ // middle22097//test "zig fmt: preserve spacing" {
2098 \\2098// try testCanonical(
2099 \\ // end2099// \\const std = @import("std");
2100 \\}2100// \\
2101 \\2101// \\pub fn main() !void {
2102 );2102// \\ var stdout_file = std.io.getStdOut;
2103}2103// \\ var stdout_file = std.io.getStdOut;
21042104// \\
2105test "zig fmt: comments before test decl" {2105// \\ var stdout_file = std.io.getStdOut;
2106 try testCanonical(2106// \\ var stdout_file = std.io.getStdOut;
2107 \\/// top level doc comment2107// \\}
2108 \\test "hi" {}2108// \\
2109 \\2109// );
2110 \\// top level normal comment2110//}
2111 \\test "hi" {}2111//
2112 \\2112//test "zig fmt: return types" {
2113 \\// middle2113// try testCanonical(
2114 \\2114// \\pub fn main() !void {}
2115 \\// end2115// \\pub fn main() anytype {}
2116 \\2116// \\pub fn main() i32 {}
2117 );2117// \\
2118}2118// );
21192119//}
2120test "zig fmt: preserve spacing" {2120//
2121 try testCanonical(2121//test "zig fmt: imports" {
2122 \\const std = @import("std");2122// try testCanonical(
2123 \\2123// \\const std = @import("std");
2124 \\pub fn main() !void {2124// \\const std = @import();
2125 \\ var stdout_file = std.io.getStdOut;2125// \\
2126 \\ var stdout_file = std.io.getStdOut;2126// );
2127 \\2127//}
2128 \\ var stdout_file = std.io.getStdOut;2128//
2129 \\ var stdout_file = std.io.getStdOut;2129//test "zig fmt: global declarations" {
2130 \\}2130// try testCanonical(
2131 \\2131// \\const a = b;
2132 );2132// \\pub const a = b;
2133}2133// \\var a = b;
21342134// \\pub var a = b;
2135test "zig fmt: return types" {2135// \\const a: i32 = b;
2136 try testCanonical(2136// \\pub const a: i32 = b;
2137 \\pub fn main() !void {}2137// \\var a: i32 = b;
2138 \\pub fn main() anytype {}2138// \\pub var a: i32 = b;
2139 \\pub fn main() i32 {}2139// \\extern const a: i32 = b;
2140 \\2140// \\pub extern const a: i32 = b;
2141 );2141// \\extern var a: i32 = b;
2142}2142// \\pub extern var a: i32 = b;
21432143// \\extern "a" const a: i32 = b;
2144test "zig fmt: imports" {2144// \\pub extern "a" const a: i32 = b;
2145 try testCanonical(2145// \\extern "a" var a: i32 = b;
2146 \\const std = @import("std");2146// \\pub extern "a" var a: i32 = b;
2147 \\const std = @import();2147// \\
2148 \\2148// );
2149 );2149//}
2150}2150//
21512151//test "zig fmt: extern declaration" {
2152test "zig fmt: global declarations" {2152// try testCanonical(
2153 try testCanonical(2153// \\extern var foo: c_int;
2154 \\const a = b;2154// \\
2155 \\pub const a = b;2155// );
2156 \\var a = b;2156//}
2157 \\pub var a = b;2157//
2158 \\const a: i32 = b;2158//test "zig fmt: alignment" {
2159 \\pub const a: i32 = b;2159// try testCanonical(
2160 \\var a: i32 = b;2160// \\var foo: c_int align(1);
2161 \\pub var a: i32 = b;2161// \\
2162 \\extern const a: i32 = b;2162// );
2163 \\pub extern const a: i32 = b;2163//}
2164 \\extern var a: i32 = b;2164//
2165 \\pub extern var a: i32 = b;2165//test "zig fmt: C main" {
2166 \\extern "a" const a: i32 = b;2166// try testCanonical(
2167 \\pub extern "a" const a: i32 = b;2167// \\fn main(argc: c_int, argv: **u8) c_int {
2168 \\extern "a" var a: i32 = b;2168// \\ const a = b;
2169 \\pub extern "a" var a: i32 = b;2169// \\}
2170 \\2170// \\
2171 );2171// );
2172}2172//}
21732173//
2174test "zig fmt: extern declaration" {2174//test "zig fmt: return" {
2175 try testCanonical(2175// try testCanonical(
2176 \\extern var foo: c_int;2176// \\fn foo(argc: c_int, argv: **u8) c_int {
2177 \\2177// \\ return 0;
2178 );2178// \\}
2179}2179// \\
21802180// \\fn bar() void {
2181test "zig fmt: alignment" {2181// \\ return;
2182 try testCanonical(2182// \\}
2183 \\var foo: c_int align(1);2183// \\
2184 \\2184// );
2185 );2185//}
2186}2186//
21872187//test "zig fmt: pointer attributes" {
2188test "zig fmt: C main" {2188// try testCanonical(
2189 try testCanonical(2189// \\extern fn f1(s: *align(*u8) u8) c_int;
2190 \\fn main(argc: c_int, argv: **u8) c_int {2190// \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
2191 \\ const a = b;2191// \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
2192 \\}2192// \\extern fn f4(s: *align(1) const volatile u8) c_int;
2193 \\2193// \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
2194 );2194// \\
2195}2195// );
21962196//}
2197test "zig fmt: return" {2197//
2198 try testCanonical(2198//test "zig fmt: slice attributes" {
2199 \\fn foo(argc: c_int, argv: **u8) c_int {2199// try testCanonical(
2200 \\ return 0;2200// \\extern fn f1(s: *align(*u8) u8) c_int;
2201 \\}2201// \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
2202 \\2202// \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
2203 \\fn bar() void {2203// \\extern fn f4(s: *align(1) const volatile u8) c_int;
2204 \\ return;2204// \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
2205 \\}2205// \\
2206 \\2206// );
2207 );2207//}
2208}2208//
22092209//test "zig fmt: test declaration" {
2210test "zig fmt: pointer attributes" {2210// try testCanonical(
2211 try testCanonical(2211// \\test "test name" {
2212 \\extern fn f1(s: *align(*u8) u8) c_int;2212// \\ const a = 1;
2213 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;2213// \\ var b = 1;
2214 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;2214// \\}
2215 \\extern fn f4(s: *align(1) const volatile u8) c_int;2215// \\
2216 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;2216// );
2217 \\2217//}
2218 );2218//
2219}2219//test "zig fmt: infix operators" {
22202220// try testCanonical(
2221test "zig fmt: slice attributes" {2221// \\test "infix operators" {
2222 try testCanonical(2222// \\ var i = undefined;
2223 \\extern fn f1(s: *align(*u8) u8) c_int;2223// \\ i = 2;
2224 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;2224// \\ i *= 2;
2225 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;2225// \\ i |= 2;
2226 \\extern fn f4(s: *align(1) const volatile u8) c_int;2226// \\ i ^= 2;
2227 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;2227// \\ i <<= 2;
2228 \\2228// \\ i >>= 2;
2229 );2229// \\ i &= 2;
2230}2230// \\ i *= 2;
22312231// \\ i *%= 2;
2232test "zig fmt: test declaration" {2232// \\ i -= 2;
2233 try testCanonical(2233// \\ i -%= 2;
2234 \\test "test name" {2234// \\ i += 2;
2235 \\ const a = 1;2235// \\ i +%= 2;
2236 \\ var b = 1;2236// \\ i /= 2;
2237 \\}2237// \\ i %= 2;
2238 \\2238// \\ _ = i == i;
2239 );2239// \\ _ = i != i;
2240}2240// \\ _ = i != i;
22412241// \\ _ = i.i;
2242test "zig fmt: infix operators" {2242// \\ _ = i || i;
2243 try testCanonical(2243// \\ _ = i!i;
2244 \\test "infix operators" {2244// \\ _ = i ** i;
2245 \\ var i = undefined;2245// \\ _ = i ++ i;
2246 \\ i = 2;2246// \\ _ = i orelse i;
2247 \\ i *= 2;2247// \\ _ = i % i;
2248 \\ i |= 2;2248// \\ _ = i / i;
2249 \\ i ^= 2;2249// \\ _ = i *% i;
2250 \\ i <<= 2;2250// \\ _ = i * i;
2251 \\ i >>= 2;2251// \\ _ = i -% i;
2252 \\ i &= 2;2252// \\ _ = i - i;
2253 \\ i *= 2;2253// \\ _ = i +% i;
2254 \\ i *%= 2;2254// \\ _ = i + i;
2255 \\ i -= 2;2255// \\ _ = i << i;
2256 \\ i -%= 2;2256// \\ _ = i >> i;
2257 \\ i += 2;2257// \\ _ = i & i;
2258 \\ i +%= 2;2258// \\ _ = i ^ i;
2259 \\ i /= 2;2259// \\ _ = i | i;
2260 \\ i %= 2;2260// \\ _ = i >= i;
2261 \\ _ = i == i;2261// \\ _ = i <= i;
2262 \\ _ = i != i;2262// \\ _ = i > i;
2263 \\ _ = i != i;2263// \\ _ = i < i;
2264 \\ _ = i.i;2264// \\ _ = i and i;
2265 \\ _ = i || i;2265// \\ _ = i or i;
2266 \\ _ = i!i;2266// \\}
2267 \\ _ = i ** i;2267// \\
2268 \\ _ = i ++ i;2268// );
2269 \\ _ = i orelse i;2269//}
2270 \\ _ = i % i;2270//
2271 \\ _ = i / i;2271//test "zig fmt: precedence" {
2272 \\ _ = i *% i;2272// try testCanonical(
2273 \\ _ = i * i;2273// \\test "precedence" {
2274 \\ _ = i -% i;2274// \\ a!b();
2275 \\ _ = i - i;2275// \\ (a!b)();
2276 \\ _ = i +% i;2276// \\ !a!b;
2277 \\ _ = i + i;2277// \\ !(a!b);
2278 \\ _ = i << i;2278// \\ !a{};
2279 \\ _ = i >> i;2279// \\ !(a{});
2280 \\ _ = i & i;2280// \\ a + b{};
2281 \\ _ = i ^ i;2281// \\ (a + b){};
2282 \\ _ = i | i;2282// \\ a << b + c;
2283 \\ _ = i >= i;2283// \\ (a << b) + c;
2284 \\ _ = i <= i;2284// \\ a & b << c;
2285 \\ _ = i > i;2285// \\ (a & b) << c;
2286 \\ _ = i < i;2286// \\ a ^ b & c;
2287 \\ _ = i and i;2287// \\ (a ^ b) & c;
2288 \\ _ = i or i;2288// \\ a | b ^ c;
2289 \\}2289// \\ (a | b) ^ c;
2290 \\2290// \\ a == b | c;
2291 );2291// \\ (a == b) | c;
2292}2292// \\ a and b == c;
22932293// \\ (a and b) == c;
2294test "zig fmt: precedence" {2294// \\ a or b and c;
2295 try testCanonical(2295// \\ (a or b) and c;
2296 \\test "precedence" {2296// \\ (a or b) and c;
2297 \\ a!b();2297// \\}
2298 \\ (a!b)();2298// \\
2299 \\ !a!b;2299// );
2300 \\ !(a!b);2300//}
2301 \\ !a{};2301//
2302 \\ !(a{});2302//test "zig fmt: prefix operators" {
2303 \\ a + b{};2303// try testCanonical(
2304 \\ (a + b){};2304// \\test "prefix operators" {
2305 \\ a << b + c;2305// \\ try return --%~!&0;
2306 \\ (a << b) + c;2306// \\}
2307 \\ a & b << c;2307// \\
2308 \\ (a & b) << c;2308// );
2309 \\ a ^ b & c;2309//}
2310 \\ (a ^ b) & c;2310//
2311 \\ a | b ^ c;2311//test "zig fmt: call expression" {
2312 \\ (a | b) ^ c;2312// try testCanonical(
2313 \\ a == b | c;2313// \\test "test calls" {
2314 \\ (a == b) | c;2314// \\ a();
2315 \\ a and b == c;2315// \\ a(1);
2316 \\ (a and b) == c;2316// \\ a(1, 2);
2317 \\ a or b and c;2317// \\ a(1, 2) + a(1, 2);
2318 \\ (a or b) and c;2318// \\}
2319 \\ (a or b) and c;2319// \\
2320 \\}2320// );
2321 \\2321//}
2322 );2322//
2323}2323//test "zig fmt: anytype type" {
23242324// try testCanonical(
2325test "zig fmt: prefix operators" {2325// \\fn print(args: anytype) anytype {}
2326 try testCanonical(2326// \\
2327 \\test "prefix operators" {2327// );
2328 \\ try return --%~!&0;2328//}
2329 \\}2329//
2330 \\2330//test "zig fmt: functions" {
2331 );2331// try testCanonical(
2332}2332// \\extern fn puts(s: *const u8) c_int;
23332333// \\extern "c" fn puts(s: *const u8) c_int;
2334test "zig fmt: call expression" {2334// \\export fn puts(s: *const u8) c_int;
2335 try testCanonical(2335// \\inline fn puts(s: *const u8) c_int;
2336 \\test "test calls" {2336// \\noinline fn puts(s: *const u8) c_int;
2337 \\ a();2337// \\pub extern fn puts(s: *const u8) c_int;
2338 \\ a(1);2338// \\pub extern "c" fn puts(s: *const u8) c_int;
2339 \\ a(1, 2);2339// \\pub export fn puts(s: *const u8) c_int;
2340 \\ a(1, 2) + a(1, 2);2340// \\pub inline fn puts(s: *const u8) c_int;
2341 \\}2341// \\pub noinline fn puts(s: *const u8) c_int;
2342 \\2342// \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
2343 );2343// \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
2344}2344// \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
23452345// \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
2346test "zig fmt: anytype type" {2346// \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
2347 try testCanonical(2347// \\
2348 \\fn print(args: anytype) anytype {}2348// );
2349 \\2349//}
2350 );2350//
2351}2351//test "zig fmt: multiline string" {
23522352// try testCanonical(
2353test "zig fmt: functions" {2353// \\test "" {
2354 try testCanonical(2354// \\ const s1 =
2355 \\extern fn puts(s: *const u8) c_int;2355// \\ \\one
2356 \\extern "c" fn puts(s: *const u8) c_int;2356// \\ \\two)
2357 \\export fn puts(s: *const u8) c_int;2357// \\ \\three
2358 \\inline fn puts(s: *const u8) c_int;2358// \\ ;
2359 \\noinline fn puts(s: *const u8) c_int;2359// \\ const s3 = // hi
2360 \\pub extern fn puts(s: *const u8) c_int;2360// \\ \\one
2361 \\pub extern "c" fn puts(s: *const u8) c_int;2361// \\ \\two)
2362 \\pub export fn puts(s: *const u8) c_int;2362// \\ \\three
2363 \\pub inline fn puts(s: *const u8) c_int;2363// \\ ;
2364 \\pub noinline fn puts(s: *const u8) c_int;2364// \\}
2365 \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;2365// \\
2366 \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;2366// );
2367 \\pub export fn puts(s: *const u8) align(2 + 2) c_int;2367//}
2368 \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;2368//
2369 \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;2369//test "zig fmt: values" {
2370 \\2370// try testCanonical(
2371 );2371// \\test "values" {
2372}2372// \\ 1;
23732373// \\ 1.0;
2374test "zig fmt: multiline string" {2374// \\ "string";
2375 try testCanonical(2375// \\ 'c';
2376 \\test "" {2376// \\ true;
2377 \\ const s1 =2377// \\ false;
2378 \\ \\one2378// \\ null;
2379 \\ \\two)2379// \\ undefined;
2380 \\ \\three2380// \\ anyerror;
2381 \\ ;2381// \\ this;
2382 \\ const s3 = // hi2382// \\ unreachable;
2383 \\ \\one2383// \\}
2384 \\ \\two)2384// \\
2385 \\ \\three2385// );
2386 \\ ;2386//}
2387 \\}2387//
2388 \\2388//test "zig fmt: indexing" {
2389 );2389// try testCanonical(
2390}2390// \\test "test index" {
23912391// \\ a[0];
2392test "zig fmt: values" {2392// \\ a[0 + 5];
2393 try testCanonical(2393// \\ a[0..];
2394 \\test "values" {2394// \\ a[0..5];
2395 \\ 1;2395// \\ a[a[0]];
2396 \\ 1.0;2396// \\ a[a[0..]];
2397 \\ "string";2397// \\ a[a[0..5]];
2398 \\ 'c';2398// \\ a[a[0]..];
2399 \\ true;2399// \\ a[a[0..5]..];
2400 \\ false;2400// \\ a[a[0]..a[0]];
2401 \\ null;2401// \\ a[a[0..5]..a[0]];
2402 \\ undefined;2402// \\ a[a[0..5]..a[0..5]];
2403 \\ anyerror;2403// \\}
2404 \\ this;2404// \\
2405 \\ unreachable;2405// );
2406 \\}2406//}
2407 \\2407//
2408 );2408//test "zig fmt: struct declaration" {
2409}2409// try testCanonical(
24102410// \\const S = struct {
2411test "zig fmt: indexing" {2411// \\ const Self = @This();
2412 try testCanonical(2412// \\ f1: u8,
2413 \\test "test index" {2413// \\ f3: u8,
2414 \\ a[0];2414// \\
2415 \\ a[0 + 5];2415// \\ f2: u8,
2416 \\ a[0..];2416// \\
2417 \\ a[0..5];2417// \\ fn method(self: *Self) Self {
2418 \\ a[a[0]];2418// \\ return self.*;
2419 \\ a[a[0..]];2419// \\ }
2420 \\ a[a[0..5]];2420// \\};
2421 \\ a[a[0]..];2421// \\
2422 \\ a[a[0..5]..];2422// \\const Ps = packed struct {
2423 \\ a[a[0]..a[0]];2423// \\ a: u8,
2424 \\ a[a[0..5]..a[0]];2424// \\ b: u8,
2425 \\ a[a[0..5]..a[0..5]];2425// \\
2426 \\}2426// \\ c: u8,
2427 \\2427// \\};
2428 );2428// \\
2429}2429// \\const Es = extern struct {
24302430// \\ a: u8,
2431test "zig fmt: struct declaration" {2431// \\ b: u8,
2432 try testCanonical(2432// \\
2433 \\const S = struct {2433// \\ c: u8,
2434 \\ const Self = @This();2434// \\};
2435 \\ f1: u8,2435// \\
2436 \\ f3: u8,2436// );
2437 \\2437//}
2438 \\ f2: u8,2438//
2439 \\2439//test "zig fmt: enum declaration" {
2440 \\ fn method(self: *Self) Self {2440// try testCanonical(
2441 \\ return self.*;2441// \\const E = enum {
2442 \\ }2442// \\ Ok,
2443 \\};2443// \\ SomethingElse = 0,
2444 \\2444// \\};
2445 \\const Ps = packed struct {2445// \\
2446 \\ a: u8,2446// \\const E2 = enum(u8) {
2447 \\ b: u8,2447// \\ Ok,
2448 \\2448// \\ SomethingElse = 255,
2449 \\ c: u8,2449// \\ SomethingThird,
2450 \\};2450// \\};
2451 \\2451// \\
2452 \\const Es = extern struct {2452// \\const Ee = extern enum {
2453 \\ a: u8,2453// \\ Ok,
2454 \\ b: u8,2454// \\ SomethingElse,
2455 \\2455// \\ SomethingThird,
2456 \\ c: u8,2456// \\};
2457 \\};2457// \\
2458 \\2458// \\const Ep = packed enum {
2459 );2459// \\ Ok,
2460}2460// \\ SomethingElse,
24612461// \\ SomethingThird,
2462test "zig fmt: enum declaration" {2462// \\};
2463 try testCanonical(2463// \\
2464 \\const E = enum {2464// );
2465 \\ Ok,2465//}
2466 \\ SomethingElse = 0,2466//
2467 \\};2467//test "zig fmt: union declaration" {
2468 \\2468// try testCanonical(
2469 \\const E2 = enum(u8) {2469// \\const U = union {
2470 \\ Ok,2470// \\ Int: u8,
2471 \\ SomethingElse = 255,2471// \\ Float: f32,
2472 \\ SomethingThird,2472// \\ None,
2473 \\};2473// \\ Bool: bool,
2474 \\2474// \\};
2475 \\const Ee = extern enum {2475// \\
2476 \\ Ok,2476// \\const Ue = union(enum) {
2477 \\ SomethingElse,2477// \\ Int: u8,
2478 \\ SomethingThird,2478// \\ Float: f32,
2479 \\};2479// \\ None,
2480 \\2480// \\ Bool: bool,
2481 \\const Ep = packed enum {2481// \\};
2482 \\ Ok,2482// \\
2483 \\ SomethingElse,2483// \\const E = enum {
2484 \\ SomethingThird,2484// \\ Int,
2485 \\};2485// \\ Float,
2486 \\2486// \\ None,
2487 );2487// \\ Bool,
2488}2488// \\};
24892489// \\
2490test "zig fmt: union declaration" {2490// \\const Ue2 = union(E) {
2491 try testCanonical(2491// \\ Int: u8,
2492 \\const U = union {2492// \\ Float: f32,
2493 \\ Int: u8,2493// \\ None,
2494 \\ Float: f32,2494// \\ Bool: bool,
2495 \\ None,2495// \\};
2496 \\ Bool: bool,2496// \\
2497 \\};2497// \\const Eu = extern union {
2498 \\2498// \\ Int: u8,
2499 \\const Ue = union(enum) {2499// \\ Float: f32,
2500 \\ Int: u8,2500// \\ None,
2501 \\ Float: f32,2501// \\ Bool: bool,
2502 \\ None,2502// \\};
2503 \\ Bool: bool,2503// \\
2504 \\};2504// );
2505 \\2505//}
2506 \\const E = enum {2506//
2507 \\ Int,2507//test "zig fmt: arrays" {
2508 \\ Float,2508// try testCanonical(
2509 \\ None,2509// \\test "test array" {
2510 \\ Bool,2510// \\ const a: [2]u8 = [2]u8{
2511 \\};2511// \\ 1,
2512 \\2512// \\ 2,
2513 \\const Ue2 = union(E) {2513// \\ };
2514 \\ Int: u8,2514// \\ const a: [2]u8 = []u8{
2515 \\ Float: f32,2515// \\ 1,
2516 \\ None,2516// \\ 2,
2517 \\ Bool: bool,2517// \\ };
2518 \\};2518// \\ const a: [0]u8 = []u8{};
2519 \\2519// \\ const x: [4:0]u8 = undefined;
2520 \\const Eu = extern union {2520// \\}
2521 \\ Int: u8,2521// \\
2522 \\ Float: f32,2522// );
2523 \\ None,2523//}
2524 \\ Bool: bool,2524//
2525 \\};2525//test "zig fmt: container initializers" {
2526 \\2526// try testCanonical(
2527 );2527// \\const a0 = []u8{};
2528}2528// \\const a1 = []u8{1};
25292529// \\const a2 = []u8{
2530test "zig fmt: arrays" {2530// \\ 1,
2531 try testCanonical(2531// \\ 2,
2532 \\test "test array" {2532// \\ 3,
2533 \\ const a: [2]u8 = [2]u8{2533// \\ 4,
2534 \\ 1,2534// \\};
2535 \\ 2,2535// \\const s0 = S{};
2536 \\ };2536// \\const s1 = S{ .a = 1 };
2537 \\ const a: [2]u8 = []u8{2537// \\const s2 = S{
2538 \\ 1,2538// \\ .a = 1,
2539 \\ 2,2539// \\ .b = 2,
2540 \\ };2540// \\};
2541 \\ const a: [0]u8 = []u8{};2541// \\
2542 \\ const x: [4:0]u8 = undefined;2542// );
2543 \\}2543//}
2544 \\2544//
2545 );2545//test "zig fmt: catch" {
2546}2546// try testCanonical(
25472547// \\test "catch" {
2548test "zig fmt: container initializers" {2548// \\ const a: anyerror!u8 = 0;
2549 try testCanonical(2549// \\ _ = a catch return;
2550 \\const a0 = []u8{};2550// \\ _ = a catch |err| return;
2551 \\const a1 = []u8{1};2551// \\}
2552 \\const a2 = []u8{2552// \\
2553 \\ 1,2553// );
2554 \\ 2,2554//}
2555 \\ 3,2555//
2556 \\ 4,2556//test "zig fmt: blocks" {
2557 \\};2557// try testCanonical(
2558 \\const s0 = S{};2558// \\test "blocks" {
2559 \\const s1 = S{ .a = 1 };2559// \\ {
2560 \\const s2 = S{2560// \\ const a = 0;
2561 \\ .a = 1,2561// \\ const b = 0;
2562 \\ .b = 2,2562// \\ }
2563 \\};2563// \\
2564 \\2564// \\ blk: {
2565 );2565// \\ const a = 0;
2566}2566// \\ const b = 0;
25672567// \\ }
2568test "zig fmt: catch" {2568// \\
2569 try testCanonical(2569// \\ const r = blk: {
2570 \\test "catch" {2570// \\ const a = 0;
2571 \\ const a: anyerror!u8 = 0;2571// \\ const b = 0;
2572 \\ _ = a catch return;2572// \\ };
2573 \\ _ = a catch |err| return;2573// \\}
2574 \\}2574// \\
2575 \\2575// );
2576 );2576//}
2577}2577//
25782578//test "zig fmt: switch" {
2579test "zig fmt: blocks" {2579// try testCanonical(
2580 try testCanonical(2580// \\test "switch" {
2581 \\test "blocks" {2581// \\ switch (0) {
2582 \\ {2582// \\ 0 => {},
2583 \\ const a = 0;2583// \\ 1 => unreachable,
2584 \\ const b = 0;2584// \\ 2, 3 => {},
2585 \\ }2585// \\ 4...7 => {},
2586 \\2586// \\ 1 + 4 * 3 + 22 => {},
2587 \\ blk: {2587// \\ else => {
2588 \\ const a = 0;2588// \\ const a = 1;
2589 \\ const b = 0;2589// \\ const b = a;
2590 \\ }2590// \\ },
2591 \\2591// \\ }
2592 \\ const r = blk: {2592// \\
2593 \\ const a = 0;2593// \\ const res = switch (0) {
2594 \\ const b = 0;2594// \\ 0 => 0,
2595 \\ };2595// \\ 1 => 2,
2596 \\}2596// \\ 1 => a = 4,
2597 \\2597// \\ else => 4,
2598 );2598// \\ };
2599}2599// \\
26002600// \\ const Union = union(enum) {
2601test "zig fmt: switch" {2601// \\ Int: i64,
2602 try testCanonical(2602// \\ Float: f64,
2603 \\test "switch" {2603// \\ };
2604 \\ switch (0) {2604// \\
2605 \\ 0 => {},2605// \\ switch (u) {
2606 \\ 1 => unreachable,2606// \\ Union.Int => |int| {},
2607 \\ 2, 3 => {},2607// \\ Union.Float => |*float| unreachable,
2608 \\ 4...7 => {},2608// \\ }
2609 \\ 1 + 4 * 3 + 22 => {},2609// \\}
2610 \\ else => {2610// \\
2611 \\ const a = 1;2611// );
2612 \\ const b = a;2612//}
2613 \\ },2613//
2614 \\ }2614//test "zig fmt: while" {
2615 \\2615// try testCanonical(
2616 \\ const res = switch (0) {2616// \\test "while" {
2617 \\ 0 => 0,2617// \\ while (10 < 1) unreachable;
2618 \\ 1 => 2,2618// \\
2619 \\ 1 => a = 4,2619// \\ while (10 < 1) unreachable else unreachable;
2620 \\ else => 4,2620// \\
2621 \\ };2621// \\ while (10 < 1) {
2622 \\2622// \\ unreachable;
2623 \\ const Union = union(enum) {2623// \\ }
2624 \\ Int: i64,2624// \\
2625 \\ Float: f64,2625// \\ while (10 < 1)
2626 \\ };2626// \\ unreachable;
2627 \\2627// \\
2628 \\ switch (u) {2628// \\ var i: usize = 0;
2629 \\ Union.Int => |int| {},2629// \\ while (i < 10) : (i += 1) {
2630 \\ Union.Float => |*float| unreachable,2630// \\ continue;
2631 \\ }2631// \\ }
2632 \\}2632// \\
2633 \\2633// \\ i = 0;
2634 );2634// \\ while (i < 10) : (i += 1)
2635}2635// \\ continue;
26362636// \\
2637test "zig fmt: while" {2637// \\ i = 0;
2638 try testCanonical(2638// \\ var j: usize = 0;
2639 \\test "while" {2639// \\ while (i < 10) : ({
2640 \\ while (10 < 1) unreachable;2640// \\ i += 1;
2641 \\2641// \\ j += 1;
2642 \\ while (10 < 1) unreachable else unreachable;2642// \\ }) {
2643 \\2643// \\ continue;
2644 \\ while (10 < 1) {2644// \\ }
2645 \\ unreachable;2645// \\
2646 \\ }2646// \\ var a: ?u8 = 2;
2647 \\2647// \\ while (a) |v| : (a = null) {
2648 \\ while (10 < 1)2648// \\ continue;
2649 \\ unreachable;2649// \\ }
2650 \\2650// \\
2651 \\ var i: usize = 0;2651// \\ while (a) |v| : (a = null)
2652 \\ while (i < 10) : (i += 1) {2652// \\ unreachable;
2653 \\ continue;2653// \\
2654 \\ }2654// \\ label: while (10 < 0) {
2655 \\2655// \\ unreachable;
2656 \\ i = 0;2656// \\ }
2657 \\ while (i < 10) : (i += 1)2657// \\
2658 \\ continue;2658// \\ const res = while (0 < 10) {
2659 \\2659// \\ break 7;
2660 \\ i = 0;2660// \\ } else {
2661 \\ var j: usize = 0;2661// \\ unreachable;
2662 \\ while (i < 10) : ({2662// \\ };
2663 \\ i += 1;2663// \\
2664 \\ j += 1;2664// \\ const res = while (0 < 10)
2665 \\ }) {2665// \\ break 7
2666 \\ continue;2666// \\ else
2667 \\ }2667// \\ unreachable;
2668 \\2668// \\
2669 \\ var a: ?u8 = 2;2669// \\ var a: anyerror!u8 = 0;
2670 \\ while (a) |v| : (a = null) {2670// \\ while (a) |v| {
2671 \\ continue;2671// \\ a = error.Err;
2672 \\ }2672// \\ } else |err| {
2673 \\2673// \\ i = 1;
2674 \\ while (a) |v| : (a = null)2674// \\ }
2675 \\ unreachable;2675// \\
2676 \\2676// \\ comptime var k: usize = 0;
2677 \\ label: while (10 < 0) {2677// \\ inline while (i < 10) : (i += 1)
2678 \\ unreachable;2678// \\ j += 2;
2679 \\ }2679// \\}
2680 \\2680// \\
2681 \\ const res = while (0 < 10) {2681// );
2682 \\ break 7;2682//}
2683 \\ } else {2683//
2684 \\ unreachable;2684//test "zig fmt: for" {
2685 \\ };2685// try testCanonical(
2686 \\2686// \\test "for" {
2687 \\ const res = while (0 < 10)2687// \\ for (a) |v| {
2688 \\ break 72688// \\ continue;
2689 \\ else2689// \\ }
2690 \\ unreachable;2690// \\
2691 \\2691// \\ for (a) |v| continue;
2692 \\ var a: anyerror!u8 = 0;2692// \\
2693 \\ while (a) |v| {2693// \\ for (a) |v| continue else return;
2694 \\ a = error.Err;2694// \\
2695 \\ } else |err| {2695// \\ for (a) |v| {
2696 \\ i = 1;2696// \\ continue;
2697 \\ }2697// \\ } else return;
2698 \\2698// \\
2699 \\ comptime var k: usize = 0;2699// \\ for (a) |v| continue else {
2700 \\ inline while (i < 10) : (i += 1)2700// \\ return;
2701 \\ j += 2;2701// \\ }
2702 \\}2702// \\
2703 \\2703// \\ for (a) |v|
2704 );2704// \\ continue
2705}2705// \\ else
27062706// \\ return;
2707test "zig fmt: for" {2707// \\
2708 try testCanonical(2708// \\ for (a) |v|
2709 \\test "for" {2709// \\ continue;
2710 \\ for (a) |v| {2710// \\
2711 \\ continue;2711// \\ for (a) |*v|
2712 \\ }2712// \\ continue;
2713 \\2713// \\
2714 \\ for (a) |v| continue;2714// \\ for (a) |v, i| {
2715 \\2715// \\ continue;
2716 \\ for (a) |v| continue else return;2716// \\ }
2717 \\2717// \\
2718 \\ for (a) |v| {2718// \\ for (a) |v, i|
2719 \\ continue;2719// \\ continue;
2720 \\ } else return;2720// \\
2721 \\2721// \\ for (a) |b| switch (b) {
2722 \\ for (a) |v| continue else {2722// \\ c => {},
2723 \\ return;2723// \\ d => {},
2724 \\ }2724// \\ };
2725 \\2725// \\
2726 \\ for (a) |v|2726// \\ for (a) |b|
2727 \\ continue2727// \\ switch (b) {
2728 \\ else2728// \\ c => {},
2729 \\ return;2729// \\ d => {},
2730 \\2730// \\ };
2731 \\ for (a) |v|2731// \\
2732 \\ continue;2732// \\ const res = for (a) |v, i| {
2733 \\2733// \\ break v;
2734 \\ for (a) |*v|2734// \\ } else {
2735 \\ continue;2735// \\ unreachable;
2736 \\2736// \\ };
2737 \\ for (a) |v, i| {2737// \\
2738 \\ continue;2738// \\ var num: usize = 0;
2739 \\ }2739// \\ inline for (a) |v, i| {
2740 \\2740// \\ num += v;
2741 \\ for (a) |v, i|2741// \\ num += i;
2742 \\ continue;2742// \\ }
2743 \\2743// \\}
2744 \\ for (a) |b| switch (b) {2744// \\
2745 \\ c => {},2745// );
2746 \\ d => {},2746//
2747 \\ };2747// try testTransform(
2748 \\2748// \\test "fix for" {
2749 \\ for (a) |b|2749// \\ for (a) |x|
2750 \\ switch (b) {2750// \\ f(x) else continue;
2751 \\ c => {},2751// \\}
2752 \\ d => {},2752// \\
2753 \\ };2753// ,
2754 \\2754// \\test "fix for" {
2755 \\ const res = for (a) |v, i| {2755// \\ for (a) |x|
2756 \\ break v;2756// \\ f(x)
2757 \\ } else {2757// \\ else continue;
2758 \\ unreachable;2758// \\}
2759 \\ };2759// \\
2760 \\2760// );
2761 \\ var num: usize = 0;2761//}
2762 \\ inline for (a) |v, i| {2762//
2763 \\ num += v;2763//test "zig fmt: if" {
2764 \\ num += i;2764// try testCanonical(
2765 \\ }2765// \\test "if" {
2766 \\}2766// \\ if (10 < 0) {
2767 \\2767// \\ unreachable;
2768 );2768// \\ }
27692769// \\
2770 try testTransform(2770// \\ if (10 < 0) unreachable;
2771 \\test "fix for" {2771// \\
2772 \\ for (a) |x|2772// \\ if (10 < 0) {
2773 \\ f(x) else continue;2773// \\ unreachable;
2774 \\}2774// \\ } else {
2775 \\2775// \\ const a = 20;
2776 ,2776// \\ }
2777 \\test "fix for" {2777// \\
2778 \\ for (a) |x|2778// \\ if (10 < 0) {
2779 \\ f(x)2779// \\ unreachable;
2780 \\ else continue;2780// \\ } else if (5 < 0) {
2781 \\}2781// \\ unreachable;
2782 \\2782// \\ } else {
2783 );2783// \\ const a = 20;
2784}2784// \\ }
27852785// \\
2786test "zig fmt: if" {2786// \\ const is_world_broken = if (10 < 0) true else false;
2787 try testCanonical(2787// \\ const some_number = 1 + if (10 < 0) 2 else 3;
2788 \\test "if" {2788// \\
2789 \\ if (10 < 0) {2789// \\ const a: ?u8 = 10;
2790 \\ unreachable;2790// \\ const b: ?u8 = null;
2791 \\ }2791// \\ if (a) |v| {
2792 \\2792// \\ const some = v;
2793 \\ if (10 < 0) unreachable;2793// \\ } else if (b) |*v| {
2794 \\2794// \\ unreachable;
2795 \\ if (10 < 0) {2795// \\ } else {
2796 \\ unreachable;2796// \\ const some = 10;
2797 \\ } else {2797// \\ }
2798 \\ const a = 20;2798// \\
2799 \\ }2799// \\ const non_null_a = if (a) |v| v else 0;
2800 \\2800// \\
2801 \\ if (10 < 0) {2801// \\ const a_err: anyerror!u8 = 0;
2802 \\ unreachable;2802// \\ if (a_err) |v| {
2803 \\ } else if (5 < 0) {2803// \\ const p = v;
2804 \\ unreachable;2804// \\ } else |err| {
2805 \\ } else {2805// \\ unreachable;
2806 \\ const a = 20;2806// \\ }
2807 \\ }2807// \\}
2808 \\2808// \\
2809 \\ const is_world_broken = if (10 < 0) true else false;2809// );
2810 \\ const some_number = 1 + if (10 < 0) 2 else 3;2810//}
2811 \\2811//
2812 \\ const a: ?u8 = 10;2812//test "zig fmt: defer" {
2813 \\ const b: ?u8 = null;2813// try testCanonical(
2814 \\ if (a) |v| {2814// \\test "defer" {
2815 \\ const some = v;2815// \\ var i: usize = 0;
2816 \\ } else if (b) |*v| {2816// \\ defer i = 1;
2817 \\ unreachable;2817// \\ defer {
2818 \\ } else {2818// \\ i += 2;
2819 \\ const some = 10;2819// \\ i *= i;
2820 \\ }2820// \\ }
2821 \\2821// \\
2822 \\ const non_null_a = if (a) |v| v else 0;2822// \\ errdefer i += 3;
2823 \\2823// \\ errdefer {
2824 \\ const a_err: anyerror!u8 = 0;2824// \\ i += 2;
2825 \\ if (a_err) |v| {2825// \\ i /= i;
2826 \\ const p = v;2826// \\ }
2827 \\ } else |err| {2827// \\}
2828 \\ unreachable;2828// \\
2829 \\ }2829// );
2830 \\}2830//}
2831 \\2831//
2832 );2832//test "zig fmt: comptime" {
2833}2833// try testCanonical(
28342834// \\fn a() u8 {
2835test "zig fmt: defer" {2835// \\ return 5;
2836 try testCanonical(2836// \\}
2837 \\test "defer" {2837// \\
2838 \\ var i: usize = 0;2838// \\fn b(comptime i: u8) u8 {
2839 \\ defer i = 1;2839// \\ return i;
2840 \\ defer {2840// \\}
2841 \\ i += 2;2841// \\
2842 \\ i *= i;2842// \\const av = comptime a();
2843 \\ }2843// \\const av2 = comptime blk: {
2844 \\2844// \\ var res = a();
2845 \\ errdefer i += 3;2845// \\ res *= b(2);
2846 \\ errdefer {2846// \\ break :blk res;
2847 \\ i += 2;2847// \\};
2848 \\ i /= i;2848// \\
2849 \\ }2849// \\comptime {
2850 \\}2850// \\ _ = a();
2851 \\2851// \\}
2852 );2852// \\
2853}2853// \\test "comptime" {
28542854// \\ const av3 = comptime a();
2855test "zig fmt: comptime" {2855// \\ const av4 = comptime blk: {
2856 try testCanonical(2856// \\ var res = a();
2857 \\fn a() u8 {2857// \\ res *= a();
2858 \\ return 5;2858// \\ break :blk res;
2859 \\}2859// \\ };
2860 \\2860// \\
2861 \\fn b(comptime i: u8) u8 {2861// \\ comptime var i = 0;
2862 \\ return i;2862// \\ comptime {
2863 \\}2863// \\ i = a();
2864 \\2864// \\ i += b(i);
2865 \\const av = comptime a();2865// \\ }
2866 \\const av2 = comptime blk: {2866// \\}
2867 \\ var res = a();2867// \\
2868 \\ res *= b(2);2868// );
2869 \\ break :blk res;2869//}
2870 \\};2870//
2871 \\2871//test "zig fmt: fn type" {
2872 \\comptime {2872// try testCanonical(
2873 \\ _ = a();2873// \\fn a(i: u8) u8 {
2874 \\}2874// \\ return i + 1;
2875 \\2875// \\}
2876 \\test "comptime" {2876// \\
2877 \\ const av3 = comptime a();2877// \\const a: fn (u8) u8 = undefined;
2878 \\ const av4 = comptime blk: {2878// \\const b: fn (u8) callconv(.Naked) u8 = undefined;
2879 \\ var res = a();2879// \\const ap: fn (u8) u8 = a;
2880 \\ res *= a();2880// \\
2881 \\ break :blk res;2881// );
2882 \\ };2882//}
2883 \\2883//
2884 \\ comptime var i = 0;2884//test "zig fmt: inline asm" {
2885 \\ comptime {2885// try testCanonical(
2886 \\ i = a();2886// \\pub fn syscall1(number: usize, arg1: usize) usize {
2887 \\ i += b(i);2887// \\ return asm volatile ("syscall"
2888 \\ }2888// \\ : [ret] "={rax}" (-> usize)
2889 \\}2889// \\ : [number] "{rax}" (number),
2890 \\2890// \\ [arg1] "{rdi}" (arg1)
2891 );2891// \\ : "rcx", "r11"
2892}2892// \\ );
28932893// \\}
2894test "zig fmt: fn type" {2894// \\
2895 try testCanonical(2895// );
2896 \\fn a(i: u8) u8 {2896//}
2897 \\ return i + 1;2897//
2898 \\}2898//test "zig fmt: async functions" {
2899 \\2899// try testCanonical(
2900 \\const a: fn (u8) u8 = undefined;2900// \\fn simpleAsyncFn() void {
2901 \\const b: fn (u8) callconv(.Naked) u8 = undefined;2901// \\ const a = async a.b();
2902 \\const ap: fn (u8) u8 = a;2902// \\ x += 1;
2903 \\2903// \\ suspend;
2904 );2904// \\ x += 1;
2905}2905// \\ suspend;
29062906// \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
2907test "zig fmt: inline asm" {2907// \\ await p;
2908 try testCanonical(2908// \\}
2909 \\pub fn syscall1(number: usize, arg1: usize) usize {2909// \\
2910 \\ return asm volatile ("syscall"2910// \\test "suspend, resume, await" {
2911 \\ : [ret] "={rax}" (-> usize)2911// \\ const p: anyframe = async testAsyncSeq();
2912 \\ : [number] "{rax}" (number),2912// \\ resume p;
2913 \\ [arg1] "{rdi}" (arg1)2913// \\ await p;
2914 \\ : "rcx", "r11"2914// \\}
2915 \\ );2915// \\
2916 \\}2916// );
2917 \\2917//}
2918 );2918//
2919}2919//test "zig fmt: nosuspend" {
29202920// try testCanonical(
2921test "zig fmt: async functions" {2921// \\const a = nosuspend foo();
2922 try testCanonical(2922// \\
2923 \\fn simpleAsyncFn() void {2923// );
2924 \\ const a = async a.b();2924//}
2925 \\ x += 1;2925//
2926 \\ suspend;2926//test "zig fmt: Block after if" {
2927 \\ x += 1;2927// try testCanonical(
2928 \\ suspend;2928// \\test "Block after if" {
2929 \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;2929// \\ if (true) {
2930 \\ await p;2930// \\ const a = 0;
2931 \\}2931// \\ }
2932 \\2932// \\
2933 \\test "suspend, resume, await" {2933// \\ {
2934 \\ const p: anyframe = async testAsyncSeq();2934// \\ const a = 0;
2935 \\ resume p;2935// \\ }
2936 \\ await p;2936// \\}
2937 \\}2937// \\
2938 \\2938// );
2939 );2939//}
2940}2940//
29412941//test "zig fmt: use" {
2942test "zig fmt: nosuspend" {2942// try testCanonical(
2943 try testCanonical(2943// \\usingnamespace @import("std");
2944 \\const a = nosuspend foo();2944// \\pub usingnamespace @import("std");
2945 \\2945// \\
2946 );2946// );
2947}2947//}
29482948//
2949test "zig fmt: Block after if" {2949//test "zig fmt: string identifier" {
2950 try testCanonical(2950// try testCanonical(
2951 \\test "Block after if" {2951// \\const @"a b" = @"c d".@"e f";
2952 \\ if (true) {2952// \\fn @"g h"() void {}
2953 \\ const a = 0;2953// \\
2954 \\ }2954// );
2955 \\2955//}
2956 \\ {2956//
2957 \\ const a = 0;2957//test "zig fmt: error return" {
2958 \\ }2958// try testCanonical(
2959 \\}2959// \\fn err() anyerror {
2960 \\2960// \\ call();
2961 );2961// \\ return error.InvalidArgs;
2962}2962// \\}
29632963// \\
2964test "zig fmt: use" {2964// );
2965 try testCanonical(2965//}
2966 \\usingnamespace @import("std");2966//
2967 \\pub usingnamespace @import("std");2967//test "zig fmt: comptime block in container" {
2968 \\2968// try testCanonical(
2969 );2969// \\pub fn container() type {
2970}2970// \\ return struct {
29712971// \\ comptime {
2972test "zig fmt: string identifier" {2972// \\ if (false) {
2973 try testCanonical(2973// \\ unreachable;
2974 \\const @"a b" = @"c d".@"e f";2974// \\ }
2975 \\fn @"g h"() void {}2975// \\ }
2976 \\2976// \\ };
2977 );2977// \\}
2978}2978// \\
29792979// );
2980test "zig fmt: error return" {2980//}
2981 try testCanonical(2981//
2982 \\fn err() anyerror {2982//test "zig fmt: inline asm parameter alignment" {
2983 \\ call();2983// try testCanonical(
2984 \\ return error.InvalidArgs;2984// \\pub fn main() void {
2985 \\}2985// \\ asm volatile (
2986 \\2986// \\ \\ foo
2987 );2987// \\ \\ bar
2988}2988// \\ );
29892989// \\ asm volatile (
2990test "zig fmt: comptime block in container" {2990// \\ \\ foo
2991 try testCanonical(2991// \\ \\ bar
2992 \\pub fn container() type {2992// \\ : [_] "" (-> usize),
2993 \\ return struct {2993// \\ [_] "" (-> usize)
2994 \\ comptime {2994// \\ );
2995 \\ if (false) {2995// \\ asm volatile (
2996 \\ unreachable;2996// \\ \\ foo
2997 \\ }2997// \\ \\ bar
2998 \\ }2998// \\ :
2999 \\ };2999// \\ : [_] "" (0),
3000 \\}3000// \\ [_] "" (0)
3001 \\3001// \\ );
3002 );3002// \\ asm volatile (
3003}3003// \\ \\ foo
30043004// \\ \\ bar
3005test "zig fmt: inline asm parameter alignment" {3005// \\ :
3006 try testCanonical(3006// \\ :
3007 \\pub fn main() void {3007// \\ : "", ""
3008 \\ asm volatile (3008// \\ );
3009 \\ \\ foo3009// \\ asm volatile (
3010 \\ \\ bar3010// \\ \\ foo
3011 \\ );3011// \\ \\ bar
3012 \\ asm volatile (3012// \\ : [_] "" (-> usize),
3013 \\ \\ foo3013// \\ [_] "" (-> usize)
3014 \\ \\ bar3014// \\ : [_] "" (0),
3015 \\ : [_] "" (-> usize),3015// \\ [_] "" (0)
3016 \\ [_] "" (-> usize)3016// \\ : "", ""
3017 \\ );3017// \\ );
3018 \\ asm volatile (3018// \\}
3019 \\ \\ foo3019// \\
3020 \\ \\ bar3020// );
3021 \\ :3021//}
3022 \\ : [_] "" (0),3022//
3023 \\ [_] "" (0)3023//test "zig fmt: multiline string in array" {
3024 \\ );3024// try testCanonical(
3025 \\ asm volatile (3025// \\const Foo = [][]const u8{
3026 \\ \\ foo3026// \\ \\aaa
3027 \\ \\ bar3027// \\ ,
3028 \\ :3028// \\ \\bbb
3029 \\ :3029// \\};
3030 \\ : "", ""3030// \\
3031 \\ );3031// \\fn bar() void {
3032 \\ asm volatile (3032// \\ const Foo = [][]const u8{
3033 \\ \\ foo3033// \\ \\aaa
3034 \\ \\ bar3034// \\ ,
3035 \\ : [_] "" (-> usize),3035// \\ \\bbb
3036 \\ [_] "" (-> usize)3036// \\ };
3037 \\ : [_] "" (0),3037// \\ const Bar = [][]const u8{ // comment here
3038 \\ [_] "" (0)3038// \\ \\aaa
3039 \\ : "", ""3039// \\ \\
3040 \\ );3040// \\ , // and another comment can go here
3041 \\}3041// \\ \\bbb
3042 \\3042// \\ };
3043 );3043// \\}
3044}3044// \\
30453045// );
3046test "zig fmt: multiline string in array" {3046//}
3047 try testCanonical(3047//
3048 \\const Foo = [][]const u8{3048//test "zig fmt: if type expr" {
3049 \\ \\aaa3049// try testCanonical(
3050 \\ ,3050// \\const mycond = true;
3051 \\ \\bbb3051// \\pub fn foo() if (mycond) i32 else void {
3052 \\};3052// \\ if (mycond) {
3053 \\3053// \\ return 42;
3054 \\fn bar() void {3054// \\ }
3055 \\ const Foo = [][]const u8{3055// \\}
3056 \\ \\aaa3056// \\
3057 \\ ,3057// );
3058 \\ \\bbb3058//}
3059 \\ };3059//test "zig fmt: file ends with struct field" {
3060 \\ const Bar = [][]const u8{ // comment here3060// try testCanonical(
3061 \\ \\aaa3061// \\a: bool
3062 \\ \\3062// \\
3063 \\ , // and another comment can go here3063// );
3064 \\ \\bbb3064//}
3065 \\ };3065//
3066 \\}3066//test "zig fmt: comment after empty comment" {
3067 \\3067// try testTransform(
3068 );3068// \\const x = true; //
3069}3069// \\//
30703070// \\//
3071test "zig fmt: if type expr" {3071// \\//a
3072 try testCanonical(3072// \\
3073 \\const mycond = true;3073// ,
3074 \\pub fn foo() if (mycond) i32 else void {3074// \\const x = true;
3075 \\ if (mycond) {3075// \\//a
3076 \\ return 42;3076// \\
3077 \\ }3077// );
3078 \\}3078//}
3079 \\3079//
3080 );3080//test "zig fmt: line comment in array" {
3081}3081// try testTransform(
3082test "zig fmt: file ends with struct field" {3082// \\test "a" {
3083 try testCanonical(3083// \\ var arr = [_]u32{
3084 \\a: bool3084// \\ 0
3085 \\3085// \\ // 1,
3086 );3086// \\ // 2,
3087}3087// \\ };
30883088// \\}
3089test "zig fmt: comment after empty comment" {3089// \\
3090 try testTransform(3090// ,
3091 \\const x = true; //3091// \\test "a" {
3092 \\//3092// \\ var arr = [_]u32{
3093 \\//3093// \\ 0, // 1,
3094 \\//a3094// \\ // 2,
3095 \\3095// \\ };
3096 ,3096// \\}
3097 \\const x = true;3097// \\
3098 \\//a3098// );
3099 \\3099// try testCanonical(
3100 );3100// \\test "a" {
3101}3101// \\ var arr = [_]u32{
31023102// \\ 0,
3103test "zig fmt: line comment in array" {3103// \\ // 1,
3104 try testTransform(3104// \\ // 2,
3105 \\test "a" {3105// \\ };
3106 \\ var arr = [_]u32{3106// \\}
3107 \\ 03107// \\
3108 \\ // 1,3108// );
3109 \\ // 2,3109//}
3110 \\ };3110//
3111 \\}3111//test "zig fmt: comment after params" {
3112 \\3112// try testTransform(
3113 ,3113// \\fn a(
3114 \\test "a" {3114// \\ b: u32
3115 \\ var arr = [_]u32{3115// \\ // c: u32,
3116 \\ 0, // 1,3116// \\ // d: u32,
3117 \\ // 2,3117// \\) void {}
3118 \\ };3118// \\
3119 \\}3119// ,
3120 \\3120// \\fn a(
3121 );3121// \\ b: u32, // c: u32,
3122 try testCanonical(3122// \\ // d: u32,
3123 \\test "a" {3123// \\) void {}
3124 \\ var arr = [_]u32{3124// \\
3125 \\ 0,3125// );
3126 \\ // 1,3126// try testCanonical(
3127 \\ // 2,3127// \\fn a(
3128 \\ };3128// \\ b: u32,
3129 \\}3129// \\ // c: u32,
3130 \\3130// \\ // d: u32,
3131 );3131// \\) void {}
3132}3132// \\
31333133// );
3134test "zig fmt: comment after params" {3134//}
3135 try testTransform(3135//
3136 \\fn a(3136//test "zig fmt: comment in array initializer/access" {
3137 \\ b: u323137// try testCanonical(
3138 \\ // c: u32,3138// \\test "a" {
3139 \\ // d: u32,3139// \\ var a = x{ //aa
3140 \\) void {}3140// \\ //bb
3141 \\3141// \\ };
3142 ,3142// \\ var a = []x{ //aa
3143 \\fn a(3143// \\ //bb
3144 \\ b: u32, // c: u32,3144// \\ };
3145 \\ // d: u32,3145// \\ var b = [ //aa
3146 \\) void {}3146// \\ _
3147 \\3147// \\ ]x{ //aa
3148 );3148// \\ //bb
3149 try testCanonical(3149// \\ 9,
3150 \\fn a(3150// \\ };
3151 \\ b: u32,3151// \\ var c = b[ //aa
3152 \\ // c: u32,3152// \\ 0
3153 \\ // d: u32,3153// \\ ];
3154 \\) void {}3154// \\ var d = [_
3155 \\3155// \\ //aa
3156 );3156// \\ ]x{ //aa
3157}3157// \\ //bb
31583158// \\ 9,
3159test "zig fmt: comment in array initializer/access" {3159// \\ };
3160 try testCanonical(3160// \\ var e = d[0
3161 \\test "a" {3161// \\ //aa
3162 \\ var a = x{ //aa3162// \\ ];
3163 \\ //bb3163// \\}
3164 \\ };3164// \\
3165 \\ var a = []x{ //aa3165// );
3166 \\ //bb3166//}
3167 \\ };3167//
3168 \\ var b = [ //aa3168//test "zig fmt: comments at several places in struct init" {
3169 \\ _3169// try testTransform(
3170 \\ ]x{ //aa3170// \\var bar = Bar{
3171 \\ //bb3171// \\ .x = 10, // test
3172 \\ 9,3172// \\ .y = "test"
3173 \\ };3173// \\ // test
3174 \\ var c = b[ //aa3174// \\};
3175 \\ 03175// \\
3176 \\ ];3176// ,
3177 \\ var d = [_3177// \\var bar = Bar{
3178 \\ //aa3178// \\ .x = 10, // test
3179 \\ ]x{ //aa3179// \\ .y = "test", // test
3180 \\ //bb3180// \\};
3181 \\ 9,3181// \\
3182 \\ };3182// );
3183 \\ var e = d[03183//
3184 \\ //aa3184// try testCanonical(
3185 \\ ];3185// \\var bar = Bar{ // test
3186 \\}3186// \\ .x = 10, // test
3187 \\3187// \\ .y = "test",
3188 );3188// \\ // test
3189}3189// \\};
31903190// \\
3191test "zig fmt: comments at several places in struct init" {3191// );
3192 try testTransform(3192//}
3193 \\var bar = Bar{3193//
3194 \\ .x = 10, // test3194//test "zig fmt: top level doc comments" {
3195 \\ .y = "test"3195// try testCanonical(
3196 \\ // test3196// \\//! tld 1
3197 \\};3197// \\//! tld 2
3198 \\3198// \\//! tld 3
3199 ,3199// \\
3200 \\var bar = Bar{3200// \\// comment
3201 \\ .x = 10, // test3201// \\
3202 \\ .y = "test", // test3202// \\/// A doc
3203 \\};3203// \\const A = struct {
3204 \\3204// \\ //! A tld 1
3205 );3205// \\ //! A tld 2
32063206// \\ //! A tld 3
3207 try testCanonical(3207// \\};
3208 \\var bar = Bar{ // test3208// \\
3209 \\ .x = 10, // test3209// \\/// B doc
3210 \\ .y = "test",3210// \\const B = struct {
3211 \\ // test3211// \\ //! B tld 1
3212 \\};3212// \\ //! B tld 2
3213 \\3213// \\ //! B tld 3
3214 );3214// \\
3215}3215// \\ /// b doc
32163216// \\ b: u32,
3217test "zig fmt: top level doc comments" {3217// \\};
3218 try testCanonical(3218// \\
3219 \\//! tld 13219// \\/// C doc
3220 \\//! tld 23220// \\const C = struct {
3221 \\//! tld 33221// \\ //! C tld 1
3222 \\3222// \\ //! C tld 2
3223 \\// comment3223// \\ //! C tld 3
3224 \\3224// \\
3225 \\/// A doc3225// \\ /// c1 doc
3226 \\const A = struct {3226// \\ c1: u32,
3227 \\ //! A tld 13227// \\
3228 \\ //! A tld 23228// \\ //! C tld 4
3229 \\ //! A tld 33229// \\ //! C tld 5
3230 \\};3230// \\ //! C tld 6
3231 \\3231// \\
3232 \\/// B doc3232// \\ /// c2 doc
3233 \\const B = struct {3233// \\ c2: u32,
3234 \\ //! B tld 13234// \\};
3235 \\ //! B tld 23235// \\
3236 \\ //! B tld 33236// );
3237 \\3237// try testCanonical(
3238 \\ /// b doc3238// \\//! Top-level documentation.
3239 \\ b: u32,3239// \\
3240 \\};3240// \\/// This is A
3241 \\3241// \\pub const A = usize;
3242 \\/// C doc3242// \\
3243 \\const C = struct {3243// );
3244 \\ //! C tld 13244// try testCanonical(
3245 \\ //! C tld 23245// \\//! Nothing here
3246 \\ //! C tld 33246// \\
3247 \\3247// );
3248 \\ /// c1 doc3248//}
3249 \\ c1: u32,3249//
3250 \\3250//test "zig fmt: extern without container keyword returns error" {
3251 \\ //! C tld 43251// try testError(
3252 \\ //! C tld 53252// \\const container = extern {};
3253 \\ //! C tld 63253// \\
3254 \\3254// , &[_]Error{
3255 \\ /// c2 doc3255// .ExpectedExpr,
3256 \\ c2: u32,3256// .ExpectedVarDeclOrFn,
3257 \\};3257// });
3258 \\3258//}
3259 );3259//
3260 try testCanonical(3260//test "zig fmt: integer literals with underscore separators" {
3261 \\//! Top-level documentation.3261// try testTransform(
3262 \\3262// \\const
3263 \\/// This is A3263// \\ x =
3264 \\pub const A = usize;3264// \\ 1_234_567
3265 \\3265// \\ +(0b0_1-0o7_0+0xff_FF ) + 0_0;
3266 );3266// ,
3267 try testCanonical(3267// \\const x =
3268 \\//! Nothing here3268// \\ 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 0_0;
3269 \\3269// \\
3270 );3270// );
3271}3271//}
32723272//
3273test "zig fmt: extern without container keyword returns error" {3273//test "zig fmt: hex literals with underscore separators" {
3274 try testError(3274// try testTransform(
3275 \\const container = extern {};3275// \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
3276 \\3276// \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
3277 , &[_]Error{3277// \\ for (c [ 0_0 .. ]) |_, i| {
3278 .ExpectedExpr,3278// \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
3279 .ExpectedVarDeclOrFn,3279// \\ }
3280 });3280// \\ return c;
3281}3281// \\}
32823282// \\
3283test "zig fmt: integer literals with underscore separators" {3283// \\
3284 try testTransform(3284// ,
3285 \\const3285// \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
3286 \\ x =3286// \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
3287 \\ 1_234_5673287// \\ for (c[0_0..]) |_, i| {
3288 \\ +(0b0_1-0o7_0+0xff_FF ) + 0_0;3288// \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
3289 ,3289// \\ }
3290 \\const x =3290// \\ return c;
3291 \\ 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 0_0;3291// \\}
3292 \\3292// \\
3293 );3293// );
3294}3294//}
32953295//
3296test "zig fmt: hex literals with underscore separators" {3296//test "zig fmt: decimal float literals with underscore separators" {
3297 try testTransform(3297// try testTransform(
3298 \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {3298// \\pub fn main() void {
3299 \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;3299// \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;
3300 \\ for (c [ 0_0 .. ]) |_, i| {3300// \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;
3301 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;3301// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3302 \\ }3302// \\}
3303 \\ return c;3303// ,
3304 \\}3304// \\pub fn main() void {
3305 \\3305// \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;
3306 \\3306// \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;
3307 ,3307// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3308 \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {3308// \\}
3309 \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;3309// \\
3310 \\ for (c[0_0..]) |_, i| {3310// );
3311 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;3311//}
3312 \\ }3312//
3313 \\ return c;3313//test "zig fmt: hexadeciaml float literals with underscore separators" {
3314 \\}3314// try testTransform(
3315 \\3315// \\pub fn main() void {
3316 );3316// \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
3317}3317// \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;
33183318// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3319test "zig fmt: decimal float literals with underscore separators" {3319// \\}
3320 try testTransform(3320// ,
3321 \\pub fn main() void {3321// \\pub fn main() void {
3322 \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;3322// \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
3323 \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;3323// \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;
3324 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3324// \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
3325 \\}3325// \\}
3326 ,3326// \\
3327 \\pub fn main() void {3327// );
3328 \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;3328//}
3329 \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;3329//
3330 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3330//test "zig fmt: convert async fn into callconv(.Async)" {
3331 \\}3331// try testTransform(
3332 \\3332// \\async fn foo() void {}
3333 );3333// ,
3334}3334// \\fn foo() callconv(.Async) void {}
33353335// \\
3336test "zig fmt: hexadeciaml float literals with underscore separators" {3336// );
3337 try testTransform(3337//}
3338 \\pub fn main() void {3338//
3339 \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;3339//test "zig fmt: convert extern fn proto into callconv(.C)" {
3340 \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;3340// try testTransform(
3341 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3341// \\extern fn foo0() void {}
3342 \\}3342// \\const foo1 = extern fn () void;
3343 ,3343// ,
3344 \\pub fn main() void {3344// \\extern fn foo0() void {}
3345 \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;3345// \\const foo1 = fn () callconv(.C) void;
3346 \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;3346// \\
3347 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });3347// );
3348 \\}3348//}
3349 \\3349//
3350 );3350//test "zig fmt: C var args" {
3351}3351// try testCanonical(
33523352// \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
3353test "zig fmt: convert async fn into callconv(.Async)" {3353// \\
3354 try testTransform(3354// );
3355 \\async fn foo() void {}3355//}
3356 ,3356//
3357 \\fn foo() callconv(.Async) void {}3357//test "zig fmt: Only indent multiline string literals in function calls" {
3358 \\3358// try testCanonical(
3359 );3359// \\test "zig fmt:" {
3360}3360// \\ try testTransform(
33613361// \\ \\const X = struct {
3362test "zig fmt: convert extern fn proto into callconv(.C)" {3362// \\ \\ foo: i32, bar: i8 };
3363 try testTransform(3363// \\ ,
3364 \\extern fn foo0() void {}3364// \\ \\const X = struct {
3365 \\const foo1 = extern fn () void;3365// \\ \\ foo: i32, bar: i8
3366 ,3366// \\ \\};
3367 \\extern fn foo0() void {}3367// \\ \\
3368 \\const foo1 = fn () callconv(.C) void;3368// \\ );
3369 \\3369// \\}
3370 );3370// \\
3371}3371// );
33723372//}
3373test "zig fmt: C var args" {3373//
3374 try testCanonical(3374//test "zig fmt: Don't add extra newline after if" {
3375 \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;3375// try testCanonical(
3376 \\3376// \\pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: []const u8) !void {
3377 );3377// \\ if (cwd().symLink(existing_path, new_path, .{})) {
3378}3378// \\ return;
33793379// \\ }
3380test "zig fmt: Only indent multiline string literals in function calls" {3380// \\}
3381 try testCanonical(3381// \\
3382 \\test "zig fmt:" {3382// );
3383 \\ try testTransform(3383//}
3384 \\ \\const X = struct {3384//
3385 \\ \\ foo: i32, bar: i8 };3385//test "zig fmt: comments in ternary ifs" {
3386 \\ ,3386// try testCanonical(
3387 \\ \\const X = struct {3387// \\const x = if (true) {
3388 \\ \\ foo: i32, bar: i83388// \\ 1;
3389 \\ \\};3389// \\} else if (false)
3390 \\ \\3390// \\ // Comment
3391 \\ );3391// \\ 0;
3392 \\}3392// \\const y = if (true)
3393 \\3393// \\ // Comment
3394 );3394// \\ 1
3395}3395// \\else
33963396// \\ 0;
3397test "zig fmt: Don't add extra newline after if" {3397// \\
3398 try testCanonical(3398// \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
3399 \\pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: []const u8) !void {3399// \\
3400 \\ if (cwd().symLink(existing_path, new_path, .{})) {3400// );
3401 \\ return;3401//}
3402 \\ }3402//
3403 \\}3403//test "zig fmt: test comments in field access chain" {
3404 \\3404// try testCanonical(
3405 );3405// \\pub const str = struct {
3406}3406// \\ pub const Thing = more.more //
34073407// \\ .more() //
3408test "zig fmt: comments in ternary ifs" {3408// \\ .more().more() //
3409 try testCanonical(3409// \\ .more() //
3410 \\const x = if (true) {3410// \\ // .more() //
3411 \\ 1;3411// \\ .more() //
3412 \\} else if (false)3412// \\ .more();
3413 \\ // Comment3413// \\ data: Data,
3414 \\ 0;3414// \\};
3415 \\const y = if (true)3415// \\
3416 \\ // Comment3416// \\pub const str = struct {
3417 \\ 13417// \\ pub const Thing = more.more //
3418 \\else3418// \\ .more() //
3419 \\ 0;3419// \\ // .more() //
3420 \\3420// \\ // .more() //
3421 \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;3421// \\ // .more() //
3422 \\3422// \\ .more() //
3423 );3423// \\ .more();
3424}3424// \\ data: Data,
34253425// \\};
3426test "zig fmt: test comments in field access chain" {3426// \\
3427 try testCanonical(3427// \\pub const str = struct {
3428 \\pub const str = struct {3428// \\ pub const Thing = more //
3429 \\ pub const Thing = more.more //3429// \\ .more //
3430 \\ .more() //3430// \\ .more() //
3431 \\ .more().more() //3431// \\ .more();
3432 \\ .more() //3432// \\ data: Data,
3433 \\ // .more() //3433// \\};
3434 \\ .more() //3434// \\
3435 \\ .more();3435// );
3436 \\ data: Data,3436//}
3437 \\};3437//
3438 \\3438//test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
3439 \\pub const str = struct {3439// try testCanonical(
3440 \\ pub const Thing = more.more //3440// \\fn foo() void {
3441 \\ .more() //3441// \\ z.display_message_dialog(
3442 \\ // .more() //3442// \\ *const [323:0]u8,
3443 \\ // .more() //3443// \\ \\Message Text
3444 \\ // .more() //3444// \\ \\------------
3445 \\ .more() //3445// \\ \\xxxxxxxxxxxx
3446 \\ .more();3446// \\ \\xxxxxxxxxxxx
3447 \\ data: Data,3447// \\ ,
3448 \\};3448// \\ g.GtkMessageType.GTK_MESSAGE_WARNING,
3449 \\3449// \\ null,
3450 \\pub const str = struct {3450// \\ );
3451 \\ pub const Thing = more //3451// \\
3452 \\ .more //3452// \\ z.display_message_dialog(*const [323:0]u8,
3453 \\ .more() //3453// \\ \\Message Text
3454 \\ .more();3454// \\ \\------------
3455 \\ data: Data,3455// \\ \\xxxxxxxxxxxx
3456 \\};3456// \\ \\xxxxxxxxxxxx
3457 \\3457// \\ , g.GtkMessageType.GTK_MESSAGE_WARNING, null);
3458 );3458// \\}
3459}3459// \\
34603460// );
3461test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {3461//}
3462 try testCanonical(3462//
3463 \\fn foo() void {3463//test "zig fmt: Control flow statement as body of blockless if" {
3464 \\ z.display_message_dialog(3464// try testCanonical(
3465 \\ *const [323:0]u8,3465// \\pub fn main() void {
3466 \\ \\Message Text3466// \\ const zoom_node = if (focused_node == layout_first)
3467 \\ \\------------3467// \\ if (it.next()) {
3468 \\ \\xxxxxxxxxxxx3468// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
3469 \\ \\xxxxxxxxxxxx3469// \\ } else null
3470 \\ ,3470// \\ else
3471 \\ g.GtkMessageType.GTK_MESSAGE_WARNING,3471// \\ focused_node;
3472 \\ null,3472// \\
3473 \\ );3473// \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
3474 \\3474// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
3475 \\ z.display_message_dialog(*const [323:0]u8,3475// \\ } else null else
3476 \\ \\Message Text3476// \\ focused_node;
3477 \\ \\------------3477// \\
3478 \\ \\xxxxxxxxxxxx3478// \\ const zoom_node = if (focused_node == layout_first)
3479 \\ \\xxxxxxxxxxxx3479// \\ if (it.next()) {
3480 \\ , g.GtkMessageType.GTK_MESSAGE_WARNING, null);3480// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
3481 \\}3481// \\ } else null;
3482 \\3482// \\
3483 );3483// \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
3484}3484// \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
34853485// \\ };
3486test "zig fmt: Control flow statement as body of blockless if" {3486// \\
3487 try testCanonical(3487// \\ const zoom_node = if (focused_node == layout_first) for (nodes) |node| {
3488 \\pub fn main() void {3488// \\ break node;
3489 \\ const zoom_node = if (focused_node == layout_first)3489// \\ };
3490 \\ if (it.next()) {3490// \\
3491 \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;3491// \\ const zoom_node = if (focused_node == layout_first) switch (nodes) {
3492 \\ } else null3492// \\ 0 => 0,
3493 \\ else3493// \\ } else
3494 \\ focused_node;3494// \\ focused_node;
3495 \\3495// \\}
3496 \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {3496// \\
3497 \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;3497// );
3498 \\ } else null else3498//}
3499 \\ focused_node;3499//
3500 \\3500//test "zig fmt: " {
3501 \\ const zoom_node = if (focused_node == layout_first)3501// try testCanonical(
3502 \\ if (it.next()) {3502// \\pub fn sendViewTags(self: Self) void {
3503 \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;3503// \\ var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));
3504 \\ } else null;3504// \\ while (it.next()) |node|
3505 \\3505// \\ view_tags.append(node.view.current_tags) catch {
3506 \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {3506// \\ c.wl_resource_post_no_memory(self.wl_resource);
3507 \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;3507// \\ log.crit(.river_status, "out of memory", .{});
3508 \\ };3508// \\ return;
3509 \\3509// \\ };
3510 \\ const zoom_node = if (focused_node == layout_first) for (nodes) |node| {3510// \\}
3511 \\ break node;3511// \\
3512 \\ };3512// );
3513 \\3513//}
3514 \\ const zoom_node = if (focused_node == layout_first) switch (nodes) {3514//
3515 \\ 0 => 0,3515//test "zig fmt: allow trailing line comments to do manual array formatting" {
3516 \\ } else3516// try testCanonical(
3517 \\ focused_node;3517// \\fn foo() void {
3518 \\}3518// \\ self.code.appendSliceAssumeCapacity(&[_]u8{
3519 \\3519// \\ 0x55, // push rbp
3520 );3520// \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
3521}3521// \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
35223522// \\ });
3523test "zig fmt: " {3523// \\
3524 try testCanonical(3524// \\ di_buf.appendAssumeCapacity(&[_]u8{
3525 \\pub fn sendViewTags(self: Self) void {3525// \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header
3526 \\ var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));3526// \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs
3527 \\ while (it.next()) |node|3527// \\ DW.AT_low_pc, DW_FORM_addr,
3528 \\ view_tags.append(node.view.current_tags) catch {3528// \\ DW.AT_high_pc, DW_FORM_addr,
3529 \\ c.wl_resource_post_no_memory(self.wl_resource);3529// \\ DW.AT_name, DW_FORM_strp,
3530 \\ log.crit(.river_status, "out of memory", .{});3530// \\ DW.AT_comp_dir, DW_FORM_strp,
3531 \\ return;3531// \\ DW.AT_producer, DW_FORM_strp,
3532 \\ };3532// \\ DW.AT_language, DW_FORM_data2,
3533 \\}3533// \\ 0, 0, // sentinel
3534 \\3534// \\ });
3535 );3535// \\
3536}3536// \\ self.code.appendSliceAssumeCapacity(&[_]u8{
35373537// \\ 0x55, // push rbp
3538test "zig fmt: allow trailing line comments to do manual array formatting" {3538// \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
3539 try testCanonical(3539// \\ // How do we handle this?
3540 \\fn foo() void {3540// \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
3541 \\ self.code.appendSliceAssumeCapacity(&[_]u8{3541// \\ // Here's a blank line, should that be allowed?
3542 \\ 0x55, // push rbp3542// \\
3543 \\ 0x48, 0x89, 0xe5, // mov rbp, rsp3543// \\ 0x48, 0x89, 0xe5,
3544 \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)3544// \\ 0x33, 0x45,
3545 \\ });3545// \\ // Now the comment breaks a single line -- how do we handle this?
3546 \\3546// \\ 0x88,
3547 \\ di_buf.appendAssumeCapacity(&[_]u8{3547// \\ });
3548 \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header3548// \\}
3549 \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs3549// \\
3550 \\ DW.AT_low_pc, DW_FORM_addr,3550// );
3551 \\ DW.AT_high_pc, DW_FORM_addr,3551//}
3552 \\ DW.AT_name, DW_FORM_strp,3552//
3553 \\ DW.AT_comp_dir, DW_FORM_strp,3553//test "zig fmt: multiline string literals should play nice with array initializers" {
3554 \\ DW.AT_producer, DW_FORM_strp,3554// try testCanonical(
3555 \\ DW.AT_language, DW_FORM_data2,3555// \\fn main() void {
3556 \\ 0, 0, // sentinel3556// \\ var a = .{.{.{.{.{.{.{.{
3557 \\ });3557// \\ 0,
3558 \\3558// \\ }}}}}}}};
3559 \\ self.code.appendSliceAssumeCapacity(&[_]u8{3559// \\ myFunc(.{
3560 \\ 0x55, // push rbp3560// \\ "aaaaaaa", "bbbbbb", "ccccc",
3561 \\ 0x48, 0x89, 0xe5, // mov rbp, rsp3561// \\ "dddd", ("eee"), ("fff"),
3562 \\ // How do we handle this?3562// \\ ("gggg"),
3563 \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)3563// \\ // Line comment
3564 \\ // Here's a blank line, should that be allowed?3564// \\ \\Multiline String Literals can be quite long
3565 \\3565// \\ ,
3566 \\ 0x48, 0x89, 0xe5,3566// \\ \\Multiline String Literals can be quite long
3567 \\ 0x33, 0x45,3567// \\ \\Multiline String Literals can be quite long
3568 \\ // Now the comment breaks a single line -- how do we handle this?3568// \\ ,
3569 \\ 0x88,3569// \\ \\Multiline String Literals can be quite long
3570 \\ });3570// \\ \\Multiline String Literals can be quite long
3571 \\}3571// \\ \\Multiline String Literals can be quite long
3572 \\3572// \\ \\Multiline String Literals can be quite long
3573 );3573// \\ ,
3574}3574// \\ (
35753575// \\ \\Multiline String Literals can be quite long
3576test "zig fmt: multiline string literals should play nice with array initializers" {3576// \\ ),
3577 try testCanonical(3577// \\ .{
3578 \\fn main() void {3578// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3579 \\ var a = .{.{.{.{.{.{.{.{3579// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3580 \\ 0,3580// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3581 \\ }}}}}}}};3581// \\ },
3582 \\ myFunc(.{3582// \\ .{(
3583 \\ "aaaaaaa", "bbbbbb", "ccccc",3583// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3584 \\ "dddd", ("eee"), ("fff"),3584// \\ )},
3585 \\ ("gggg"),3585// \\ .{
3586 \\ // Line comment3586// \\ "xxxxxxx", "xxx",
3587 \\ \\Multiline String Literals can be quite long3587// \\ (
3588 \\ ,3588// \\ \\ xxx
3589 \\ \\Multiline String Literals can be quite long3589// \\ ),
3590 \\ \\Multiline String Literals can be quite long3590// \\ "xxx", "xxx",
3591 \\ ,3591// \\ },
3592 \\ \\Multiline String Literals can be quite long3592// \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" }, .{ "xxxxxxx", "xxx", "xxx", "xxx" },
3593 \\ \\Multiline String Literals can be quite long3593// \\ "aaaaaaa", "bbbbbb", "ccccc", // -
3594 \\ \\Multiline String Literals can be quite long3594// \\ "dddd", ("eee"), ("fff"),
3595 \\ \\Multiline String Literals can be quite long3595// \\ .{
3596 \\ ,3596// \\ "xxx", "xxx",
3597 \\ (3597// \\ (
3598 \\ \\Multiline String Literals can be quite long3598// \\ \\ xxx
3599 \\ ),3599// \\ ),
3600 \\ .{3600// \\ "xxxxxxxxxxxxxx", "xxx",
3601 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3601// \\ },
3602 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3602// \\ .{
3603 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3603// \\ (
3604 \\ },3604// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3605 \\ .{(3605// \\ ),
3606 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3606// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3607 \\ )},3607// \\ },
3608 \\ .{3608// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3609 \\ "xxxxxxx", "xxx",3609// \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3610 \\ (3610// \\ });
3611 \\ \\ xxx3611// \\}
3612 \\ ),3612// \\
3613 \\ "xxx", "xxx",3613// );
3614 \\ },3614//}
3615 \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" }, .{ "xxxxxxx", "xxx", "xxx", "xxx" },3615//
3616 \\ "aaaaaaa", "bbbbbb", "ccccc", // -3616//test "zig fmt: use of comments and Multiline string literals may force the parameters over multiple lines" {
3617 \\ "dddd", ("eee"), ("fff"),3617// try testCanonical(
3618 \\ .{3618// \\pub fn makeMemUndefined(qzz: []u8) i1 {
3619 \\ "xxx", "xxx",3619// \\ cases.add( // fixed bug #2032
3620 \\ (3620// \\ "compile diagnostic string for top level decl type",
3621 \\ \\ xxx3621// \\ \\export fn entry() void {
3622 \\ ),3622// \\ \\ var foo: u32 = @This(){};
3623 \\ "xxxxxxxxxxxxxx", "xxx",3623// \\ \\}
3624 \\ },3624// \\ , &[_][]const u8{
3625 \\ .{3625// \\ "tmp.zig:2:27: error: type 'u32' does not support array initialization",
3626 \\ (3626// \\ });
3627 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3627// \\ @compileError(
3628 \\ ),3628// \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
3629 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3629// \\ \\ Consider providing your own hash function.
3630 \\ },3630// \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
3631 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3631// \\ \\ Consider providing your own hash function.
3632 \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3632// \\ );
3633 \\ });3633// \\ return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
3634 \\}3634// \\ .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
3635 \\3635// \\}
3636 );3636// \\
3637}3637// \\// This looks like garbage don't do this
36383638// \\const rparen = tree.prevToken(
3639test "zig fmt: use of comments and Multiline string literals may force the parameters over multiple lines" {3639// \\// the first token for the annotation expressions is the left
3640 try testCanonical(3640// \\// parenthesis, hence the need for two prevToken
3641 \\pub fn makeMemUndefined(qzz: []u8) i1 {3641// \\ if (fn_proto.getAlignExpr()) |align_expr|
3642 \\ cases.add( // fixed bug #20323642// \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))
3643 \\ "compile diagnostic string for top level decl type",3643// \\else if (fn_proto.getSectionExpr()) |section_expr|
3644 \\ \\export fn entry() void {3644// \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))
3645 \\ \\ var foo: u32 = @This(){};3645// \\else if (fn_proto.getCallconvExpr()) |callconv_expr|
3646 \\ \\}3646// \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
3647 \\ , &[_][]const u8{3647// \\else switch (fn_proto.return_type) {
3648 \\ "tmp.zig:2:27: error: type 'u32' does not support array initialization",3648// \\ .Explicit => |node| node.firstToken(),
3649 \\ });3649// \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),
3650 \\ @compileError(3650// \\ .Invalid => unreachable,
3651 \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.3651// \\});
3652 \\ \\ Consider providing your own hash function.3652// \\
3653 \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.3653// );
3654 \\ \\ Consider providing your own hash function.3654//}
3655 \\ );3655//
3656 \\ return @intCast(i1, doMemCheckClientRequestExpr(0, // default return3656//test "zig fmt: single argument trailing commas in @builtins()" {
3657 \\ .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));3657// try testCanonical(
3658 \\}3658// \\pub fn foo(qzz: []u8) i1 {
3659 \\3659// \\ @panic(
3660 \\// This looks like garbage don't do this3660// \\ foo,
3661 \\const rparen = tree.prevToken(3661// \\ );
3662 \\// the first token for the annotation expressions is the left3662// \\ panic(
3663 \\// parenthesis, hence the need for two prevToken3663// \\ foo,
3664 \\ if (fn_proto.getAlignExpr()) |align_expr|3664// \\ );
3665 \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))3665// \\ @panic(
3666 \\else if (fn_proto.getSectionExpr()) |section_expr|3666// \\ foo,
3667 \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))3667// \\ bar,
3668 \\else if (fn_proto.getCallconvExpr()) |callconv_expr|3668// \\ );
3669 \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))3669// \\}
3670 \\else switch (fn_proto.return_type) {3670// \\
3671 \\ .Explicit => |node| node.firstToken(),3671// );
3672 \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),3672//}
3673 \\ .Invalid => unreachable,3673//
3674 \\});3674//test "zig fmt: trailing comma should force multiline 1 column" {
3675 \\3675// try testTransform(
3676 );3676// \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
3677}3677// \\
36783678// ,
3679test "zig fmt: single argument trailing commas in @builtins()" {3679// \\pub const UUID_NULL: uuid_t = [16]u8{
3680 try testCanonical(3680// \\ 0,
3681 \\pub fn foo(qzz: []u8) i1 {3681// \\ 0,
3682 \\ @panic(3682// \\ 0,
3683 \\ foo,3683// \\ 0,
3684 \\ );3684// \\};
3685 \\ panic(3685// \\
3686 \\ foo,3686// );
3687 \\ );3687//}
3688 \\ @panic(3688//
3689 \\ foo,3689//test "zig fmt: function params should align nicely" {
3690 \\ bar,3690// try testCanonical(
3691 \\ );3691// \\pub fn foo() void {
3692 \\}3692// \\ cases.addRuntimeSafety("slicing operator with sentinel",
3693 \\3693// \\ \\const std = @import("std");
3694 );3694// \\ ++ check_panic_msg ++
3695}3695// \\ \\pub fn main() void {
36963696// \\ \\ var buf = [4]u8{'a','b','c',0};
3697test "zig fmt: trailing comma should force multiline 1 column" {3697// \\ \\ const slice = buf[0..:0];
3698 try testTransform(3698// \\ \\}
3699 \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};3699// \\ );
3700 \\3700// \\}
3701 ,3701// \\
3702 \\pub const UUID_NULL: uuid_t = [16]u8{3702// );
3703 \\ 0,3703//}
3704 \\ 0,
3705 \\ 0,
3706 \\ 0,
3707 \\};
3708 \\
3709 );
3710}
3711
3712test "zig fmt: function params should align nicely" {
3713 try testCanonical(
3714 \\pub fn foo() void {
3715 \\ cases.addRuntimeSafety("slicing operator with sentinel",
3716 \\ \\const std = @import("std");
3717 \\ ++ check_panic_msg ++
3718 \\ \\pub fn main() void {
3719 \\ \\ var buf = [4]u8{'a','b','c',0};
3720 \\ \\ const slice = buf[0..:0];
3721 \\ \\}
3722 \\ );
3723 \\}
3724 \\
3725 );
3726}
37273704
3728const std = @import("std");3705const std = @import("std");
3729const mem = std.mem;3706const mem = std.mem;
...@@ -3763,8 +3740,10 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b...@@ -3763,8 +3740,10 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
3763 errdefer buffer.deinit();3740 errdefer buffer.deinit();
37643741
3765 const writer = buffer.writer();3742 const writer = buffer.writer();
3766 anything_changed.* = try std.zig.render(allocator, writer, tree);3743 try std.zig.render(allocator, writer, tree);
3767 return buffer.toOwnedSlice();3744 const result = buffer.toOwnedSlice();
3745 anything_changed.* = !mem.eql(u8, result, source);
3746 return result;
3768}3747}
3769fn testTransform(source: []const u8, expected_source: []const u8) !void {3748fn testTransform(source: []const u8, expected_source: []const u8) !void {
3770 const needed_alloc_count = x: {3749 const needed_alloc_count = x: {
lib/std/zig/render.zig+2128-2341
...@@ -14,2167 +14,2072 @@ const indent_delta = 4;...@@ -14,2167 +14,2072 @@ const indent_delta = 4;
14const asm_indent_delta = 2;14const asm_indent_delta = 2;
1515
16pub const Error = error{16pub const Error = error{
17 /// Ran out of memory allocating call stack frames to complete rendering.17 /// Ran out of memory allocating call stack frames to complete rendering, or
18 /// ran out of memory allocating space in the output buffer.
18 OutOfMemory,19 OutOfMemory,
19};20};
2021
21/// Returns whether anything changed22const Writer = std.ArrayList(u8).Writer;
22pub fn render(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tree) (@TypeOf(stream).Error || Error)!bool {23const Ais = std.io.AutoIndentingStream(Writer);
23 // cannot render an invalid tree
24 std.debug.assert(tree.errors.len == 0);
2524
26 var change_detection_stream = std.io.changeDetectionStream(tree.source, stream);25/// Returns whether anything changed.
27 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, change_detection_stream.writer());26/// `gpa` is used for allocating extra stack memory if needed, because
2827/// this function utilizes recursion.
29 try renderRoot(allocator, &auto_indenting_stream, tree);28pub fn render(gpa: *mem.Allocator, writer: Writer, tree: ast.Tree) Error!void {
3029 assert(tree.errors.len == 0); // cannot render an invalid tree
31 return change_detection_stream.changeDetected();30 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, writer);
32}31 try renderRoot(&auto_indenting_stream, tree);
3332}
34fn renderRoot(
35 allocator: *mem.Allocator,
36 ais: anytype,
37 tree: *ast.Tree,
38) (@TypeOf(ais.*).Error || Error)!void {
39
40 // render all the line comments at the beginning of the file
41 for (tree.token_ids) |token_id, i| {
42 if (token_id != .LineComment) break;
43 const token_loc = tree.token_locs[i];
44 try ais.writer().print("{s}\n", .{mem.trimRight(u8, tree.tokenSliceLoc(token_loc), " ")});
45 const next_token = tree.token_locs[i + 1];
46 const loc = tree.tokenLocationLoc(token_loc.end, next_token);
47 if (loc.line >= 2) {
48 try ais.insertNewline();
49 }
50 }
51
52 var decl_i: ast.NodeIndex = 0;
53 const root_decls = tree.root_node.decls();
54
55 if (root_decls.len == 0) return;
56 while (true) {
57 var decl = root_decls[decl_i];
58
59 // This loop does the following:
60 //
61 // - Iterates through line/doc comment tokens that precedes the current
62 // decl.
63 // - Figures out the first token index (`copy_start_token_index`) which
64 // hasn't been copied to the output stream yet.
65 // - Detects `zig fmt: (off|on)` in the line comment tokens, and
66 // determines whether the current decl should be reformatted or not.
67 //
68 var token_index = decl.firstToken();
69 var fmt_active = true;
70 var found_fmt_directive = false;
71
72 var copy_start_token_index = token_index;
73
74 while (token_index != 0) {
75 token_index -= 1;
76 const token_id = tree.token_ids[token_index];
77 switch (token_id) {
78 .LineComment => {},
79 .DocComment => {
80 copy_start_token_index = token_index;
81 continue;
82 },
83 else => break,
84 }
85
86 const token_loc = tree.token_locs[token_index];
87 if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: off")) {
88 if (!found_fmt_directive) {
89 fmt_active = false;
90 found_fmt_directive = true;
91 }
92 } else if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: on")) {
93 if (!found_fmt_directive) {
94 fmt_active = true;
95 found_fmt_directive = true;
96 }
97 }
98 }
99
100 if (!fmt_active) {
101 // Reformatting is disabled for the current decl and possibly some
102 // more decls that follow.
103 // Find the next `decl` for which reformatting is re-enabled.
104 token_index = decl.firstToken();
105
106 while (!fmt_active) {
107 decl_i += 1;
108 if (decl_i >= root_decls.len) {
109 // If there's no next reformatted `decl`, just copy the
110 // remaining input tokens and bail out.
111 const start = tree.token_locs[copy_start_token_index].start;
112 try copyFixingWhitespace(ais, tree.source[start..]);
113 return;
114 }
115 decl = root_decls[decl_i];
116 var decl_first_token_index = decl.firstToken();
117
118 while (token_index < decl_first_token_index) : (token_index += 1) {
119 const token_id = tree.token_ids[token_index];
120 switch (token_id) {
121 .LineComment => {},
122 .Eof => unreachable,
123 else => continue,
124 }
125 const token_loc = tree.token_locs[token_index];
126 if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: on")) {
127 fmt_active = true;
128 } else if (mem.eql(u8, mem.trim(u8, tree.tokenSliceLoc(token_loc)[2..], " "), "zig fmt: off")) {
129 fmt_active = false;
130 }
131 }
132 }
133
134 // Found the next `decl` for which reformatting is enabled. Copy
135 // the input tokens before the `decl` that haven't been copied yet.
136 var copy_end_token_index = decl.firstToken();
137 token_index = copy_end_token_index;
138 while (token_index != 0) {
139 token_index -= 1;
140 const token_id = tree.token_ids[token_index];
141 switch (token_id) {
142 .LineComment => {},
143 .DocComment => {
144 copy_end_token_index = token_index;
145 continue;
146 },
147 else => break,
148 }
149 }
150
151 const start = tree.token_locs[copy_start_token_index].start;
152 const end = tree.token_locs[copy_end_token_index].start;
153 try copyFixingWhitespace(ais, tree.source[start..end]);
154 }
155
156 try renderTopLevelDecl(allocator, ais, tree, decl);
157 decl_i += 1;
158 if (decl_i >= root_decls.len) return;
159 try renderExtraNewline(tree, ais, root_decls[decl_i]);
160 }
161}
162
163fn renderExtraNewline(tree: *ast.Tree, ais: anytype, node: *ast.Node) @TypeOf(ais.*).Error!void {
164 return renderExtraNewlineToken(tree, ais, node.firstToken());
165}
166
167fn renderExtraNewlineToken(
168 tree: *ast.Tree,
169 ais: anytype,
170 first_token: ast.TokenIndex,
171) @TypeOf(ais.*).Error!void {
172 var prev_token = first_token;
173 if (prev_token == 0) return;
174 var newline_threshold: usize = 2;
175 while (tree.token_ids[prev_token - 1] == .DocComment) {
176 if (tree.tokenLocation(tree.token_locs[prev_token - 1].end, prev_token).line == 1) {
177 newline_threshold += 1;
178 }
179 prev_token -= 1;
180 }
181 const prev_token_end = tree.token_locs[prev_token - 1].end;
182 const loc = tree.tokenLocation(prev_token_end, first_token);
183 if (loc.line >= newline_threshold) {
184 try ais.insertNewline();
185 }
186}
187
188fn renderTopLevelDecl(allocator: *mem.Allocator, ais: anytype, tree: *ast.Tree, decl: *ast.Node) (@TypeOf(ais.*).Error || Error)!void {
189 try renderContainerDecl(allocator, ais, tree, decl, .Newline);
190}
191
192fn renderContainerDecl(allocator: *mem.Allocator, ais: anytype, tree: *ast.Tree, decl: *ast.Node, space: Space) (@TypeOf(ais.*).Error || Error)!void {
193 switch (decl.tag) {
194 .FnProto => {
195 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
196
197 try renderDocComments(tree, ais, fn_proto, fn_proto.getDocComments());
198
199 if (fn_proto.getBodyNode()) |body_node| {
200 try renderExpression(allocator, ais, tree, decl, .Space);
201 try renderExpression(allocator, ais, tree, body_node, space);
202 } else {
203 try renderExpression(allocator, ais, tree, decl, .None);
204 try renderToken(tree, ais, tree.nextToken(decl.lastToken()), space);
205 }
206 },
207
208 .Use => {
209 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
210
211 if (use_decl.visib_token) |visib_token| {
212 try renderToken(tree, ais, visib_token, .Space); // pub
213 }
214 try renderToken(tree, ais, use_decl.use_token, .Space); // usingnamespace
215 try renderExpression(allocator, ais, tree, use_decl.expr, .None);
216 try renderToken(tree, ais, use_decl.semicolon_token, space); // ;
217 },
218
219 .VarDecl => {
220 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
221
222 try renderDocComments(tree, ais, var_decl, var_decl.getDocComments());
223 try renderVarDecl(allocator, ais, tree, var_decl);
224 },
225
226 .TestDecl => {
227 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
228
229 try renderDocComments(tree, ais, test_decl, test_decl.doc_comments);
230 try renderToken(tree, ais, test_decl.test_token, .Space);
231 if (test_decl.name) |name|
232 try renderExpression(allocator, ais, tree, name, .Space);
233 try renderExpression(allocator, ais, tree, test_decl.body_node, space);
234 },
235
236 .ContainerField => {
237 const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
238
239 try renderDocComments(tree, ais, field, field.doc_comments);
240 if (field.comptime_token) |t| {
241 try renderToken(tree, ais, t, .Space); // comptime
242 }
243
244 const src_has_trailing_comma = blk: {
245 const maybe_comma = tree.nextToken(field.lastToken());
246 break :blk tree.token_ids[maybe_comma] == .Comma;
247 };
248
249 // The trailing comma is emitted at the end, but if it's not present
250 // we still have to respect the specified `space` parameter
251 const last_token_space: Space = if (src_has_trailing_comma) .None else space;
252
253 if (field.type_expr == null and field.value_expr == null) {
254 try renderToken(tree, ais, field.name_token, last_token_space); // name
255 } else if (field.type_expr != null and field.value_expr == null) {
256 try renderToken(tree, ais, field.name_token, .None); // name
257 try renderToken(tree, ais, tree.nextToken(field.name_token), .Space); // :
258
259 if (field.align_expr) |align_value_expr| {
260 try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
261 const lparen_token = tree.prevToken(align_value_expr.firstToken());
262 const align_kw = tree.prevToken(lparen_token);
263 const rparen_token = tree.nextToken(align_value_expr.lastToken());
264 try renderToken(tree, ais, align_kw, .None); // align
265 try renderToken(tree, ais, lparen_token, .None); // (
266 try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
267 try renderToken(tree, ais, rparen_token, last_token_space); // )
268 } else {
269 try renderExpression(allocator, ais, tree, field.type_expr.?, last_token_space); // type
270 }
271 } else if (field.type_expr == null and field.value_expr != null) {
272 try renderToken(tree, ais, field.name_token, .Space); // name
273 try renderToken(tree, ais, tree.nextToken(field.name_token), .Space); // =
274 try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
275 } else {
276 try renderToken(tree, ais, field.name_token, .None); // name
277 try renderToken(tree, ais, tree.nextToken(field.name_token), .Space); // :
278
279 if (field.align_expr) |align_value_expr| {
280 try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
281 const lparen_token = tree.prevToken(align_value_expr.firstToken());
282 const align_kw = tree.prevToken(lparen_token);
283 const rparen_token = tree.nextToken(align_value_expr.lastToken());
284 try renderToken(tree, ais, align_kw, .None); // align
285 try renderToken(tree, ais, lparen_token, .None); // (
286 try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
287 try renderToken(tree, ais, rparen_token, .Space); // )
288 } else {
289 try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
290 }
291 try renderToken(tree, ais, tree.prevToken(field.value_expr.?.firstToken()), .Space); // =
292 try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
293 }
294
295 if (src_has_trailing_comma) {
296 const comma = tree.nextToken(field.lastToken());
297 try renderToken(tree, ais, comma, space);
298 }
299 },
300
301 .Comptime => {
302 assert(!decl.requireSemiColon());
303 try renderExpression(allocator, ais, tree, decl, space);
304 },
305
306 .DocComment => {
307 const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl);
308 const kind = tree.token_ids[comment.first_line];
309 try renderToken(tree, ais, comment.first_line, .Newline);
310 var tok_i = comment.first_line + 1;
311 while (true) : (tok_i += 1) {
312 const tok_id = tree.token_ids[tok_i];
313 if (tok_id == kind) {
314 try renderToken(tree, ais, tok_i, .Newline);
315 } else if (tok_id == .LineComment) {
316 continue;
317 } else {
318 break;
319 }
320 }
321 },
322 else => unreachable,
323 }
324}
325
326fn renderExpression(
327 allocator: *mem.Allocator,
328 ais: anytype,
329 tree: *ast.Tree,
330 base: *ast.Node,
331 space: Space,
332) (@TypeOf(ais.*).Error || Error)!void {
333 switch (base.tag) {
334 .Identifier,
335 .IntegerLiteral,
336 .FloatLiteral,
337 .StringLiteral,
338 .CharLiteral,
339 .BoolLiteral,
340 .NullLiteral,
341 .Unreachable,
342 .ErrorType,
343 .UndefinedLiteral,
344 => {
345 const casted_node = base.cast(ast.Node.OneToken).?;
346 return renderToken(tree, ais, casted_node.token, space);
347 },
348
349 .AnyType => {
350 const any_type = base.castTag(.AnyType).?;
351 if (mem.eql(u8, tree.tokenSlice(any_type.token), "var")) {
352 // TODO remove in next release cycle
353 try ais.writer().writeAll("anytype");
354 if (space == .Comma) try ais.writer().writeAll(",\n");
355 return;
356 }
357 return renderToken(tree, ais, any_type.token, space);
358 },
359
360 .Block, .LabeledBlock => {
361 const block: struct {
362 label: ?ast.TokenIndex,
363 statements: []*ast.Node,
364 lbrace: ast.TokenIndex,
365 rbrace: ast.TokenIndex,
366 } = b: {
367 if (base.castTag(.Block)) |block| {
368 break :b .{
369 .label = null,
370 .statements = block.statements(),
371 .lbrace = block.lbrace,
372 .rbrace = block.rbrace,
373 };
374 } else if (base.castTag(.LabeledBlock)) |block| {
375 break :b .{
376 .label = block.label,
377 .statements = block.statements(),
378 .lbrace = block.lbrace,
379 .rbrace = block.rbrace,
380 };
381 } else {
382 unreachable;
383 }
384 };
385
386 if (block.label) |label| {
387 try renderToken(tree, ais, label, Space.None);
388 try renderToken(tree, ais, tree.nextToken(label), Space.Space);
389 }
390
391 if (block.statements.len == 0) {
392 ais.pushIndentNextLine();
393 defer ais.popIndent();
394 try renderToken(tree, ais, block.lbrace, Space.None);
395 } else {
396 ais.pushIndentNextLine();
397 defer ais.popIndent();
398
399 try renderToken(tree, ais, block.lbrace, Space.Newline);
400
401 for (block.statements) |statement, i| {
402 try renderStatement(allocator, ais, tree, statement);
403
404 if (i + 1 < block.statements.len) {
405 try renderExtraNewline(tree, ais, block.statements[i + 1]);
406 }
407 }
408 }
409 return renderToken(tree, ais, block.rbrace, space);
410 },
411
412 .Defer => {
413 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
414
415 try renderToken(tree, ais, defer_node.defer_token, Space.Space);
416 if (defer_node.payload) |payload| {
417 try renderExpression(allocator, ais, tree, payload, Space.Space);
418 }
419 return renderExpression(allocator, ais, tree, defer_node.expr, space);
420 },
421 .Comptime => {
422 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
423
424 try renderToken(tree, ais, comptime_node.comptime_token, Space.Space);
425 return renderExpression(allocator, ais, tree, comptime_node.expr, space);
426 },
427 .Nosuspend => {
428 const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base);
429 if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) {
430 // TODO: remove this
431 try ais.writer().writeAll("nosuspend ");
432 } else {
433 try renderToken(tree, ais, nosuspend_node.nosuspend_token, Space.Space);
434 }
435 return renderExpression(allocator, ais, tree, nosuspend_node.expr, space);
436 },
437
438 .Suspend => {
439 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
440
441 if (suspend_node.body) |body| {
442 try renderToken(tree, ais, suspend_node.suspend_token, Space.Space);
443 return renderExpression(allocator, ais, tree, body, space);
444 } else {
445 return renderToken(tree, ais, suspend_node.suspend_token, space);
446 }
447 },
448
449 .Catch => {
450 const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base);
451
452 const op_space = Space.Space;
453 try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
454
455 const after_op_space = blk: {
456 const same_line = tree.tokensOnSameLine(infix_op_node.op_token, tree.nextToken(infix_op_node.op_token));
457 break :blk if (same_line) op_space else Space.Newline;
458 };
459
460 try renderToken(tree, ais, infix_op_node.op_token, after_op_space);
461
462 if (infix_op_node.payload) |payload| {
463 try renderExpression(allocator, ais, tree, payload, Space.Space);
464 }
465
466 ais.pushIndentOneShot();
467 return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
468 },
469
470 .Add,
471 .AddWrap,
472 .ArrayCat,
473 .ArrayMult,
474 .Assign,
475 .AssignBitAnd,
476 .AssignBitOr,
477 .AssignBitShiftLeft,
478 .AssignBitShiftRight,
479 .AssignBitXor,
480 .AssignDiv,
481 .AssignSub,
482 .AssignSubWrap,
483 .AssignMod,
484 .AssignAdd,
485 .AssignAddWrap,
486 .AssignMul,
487 .AssignMulWrap,
488 .BangEqual,
489 .BitAnd,
490 .BitOr,
491 .BitShiftLeft,
492 .BitShiftRight,
493 .BitXor,
494 .BoolAnd,
495 .BoolOr,
496 .Div,
497 .EqualEqual,
498 .ErrorUnion,
499 .GreaterOrEqual,
500 .GreaterThan,
501 .LessOrEqual,
502 .LessThan,
503 .MergeErrorSets,
504 .Mod,
505 .Mul,
506 .MulWrap,
507 .Period,
508 .Range,
509 .Sub,
510 .SubWrap,
511 .OrElse,
512 => {
513 const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base);
514
515 const op_space = switch (base.tag) {
516 .Period, .ErrorUnion, .Range => Space.None,
517 else => Space.Space,
518 };
519 try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
520
521 const after_op_space = blk: {
522 const loc = tree.tokenLocation(tree.token_locs[infix_op_node.op_token].end, tree.nextToken(infix_op_node.op_token));
523 break :blk if (loc.line == 0) op_space else Space.Newline;
524 };
525
526 {
527 ais.pushIndent();
528 defer ais.popIndent();
529 try renderToken(tree, ais, infix_op_node.op_token, after_op_space);
530 }
531 ais.pushIndentOneShot();
532 return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
533 },
534
535 .BitNot,
536 .BoolNot,
537 .Negation,
538 .NegationWrap,
539 .OptionalType,
540 .AddressOf,
541 => {
542 const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
543 try renderToken(tree, ais, casted_node.op_token, Space.None);
544 return renderExpression(allocator, ais, tree, casted_node.rhs, space);
545 },
546
547 .Try,
548 .Resume,
549 .Await,
550 => {
551 const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
552 try renderToken(tree, ais, casted_node.op_token, Space.Space);
553 return renderExpression(allocator, ais, tree, casted_node.rhs, space);
554 },
555
556 .ArrayType => {
557 const array_type = @fieldParentPtr(ast.Node.ArrayType, "base", base);
558 return renderArrayType(
559 allocator,
560 ais,
561 tree,
562 array_type.op_token,
563 array_type.rhs,
564 array_type.len_expr,
565 null,
566 space,
567 );
568 },
569 .ArrayTypeSentinel => {
570 const array_type = @fieldParentPtr(ast.Node.ArrayTypeSentinel, "base", base);
571 return renderArrayType(
572 allocator,
573 ais,
574 tree,
575 array_type.op_token,
576 array_type.rhs,
577 array_type.len_expr,
578 array_type.sentinel,
579 space,
580 );
581 },
582
583 .PtrType => {
584 const ptr_type = @fieldParentPtr(ast.Node.PtrType, "base", base);
585 const op_tok_id = tree.token_ids[ptr_type.op_token];
586 switch (op_tok_id) {
587 .Asterisk, .AsteriskAsterisk => try ais.writer().writeByte('*'),
588 .LBracket => if (tree.token_ids[ptr_type.op_token + 2] == .Identifier)
589 try ais.writer().writeAll("[*c")
590 else
591 try ais.writer().writeAll("[*"),
592 else => unreachable,
593 }
594 if (ptr_type.ptr_info.sentinel) |sentinel| {
595 const colon_token = tree.prevToken(sentinel.firstToken());
596 try renderToken(tree, ais, colon_token, Space.None); // :
597 const sentinel_space = switch (op_tok_id) {
598 .LBracket => Space.None,
599 else => Space.Space,
600 };
601 try renderExpression(allocator, ais, tree, sentinel, sentinel_space);
602 }
603 switch (op_tok_id) {
604 .Asterisk, .AsteriskAsterisk => {},
605 .LBracket => try ais.writer().writeByte(']'),
606 else => unreachable,
607 }
608 if (ptr_type.ptr_info.allowzero_token) |allowzero_token| {
609 try renderToken(tree, ais, allowzero_token, Space.Space); // allowzero
610 }
611 if (ptr_type.ptr_info.align_info) |align_info| {
612 const lparen_token = tree.prevToken(align_info.node.firstToken());
613 const align_token = tree.prevToken(lparen_token);
614
615 try renderToken(tree, ais, align_token, Space.None); // align
616 try renderToken(tree, ais, lparen_token, Space.None); // (
617
618 try renderExpression(allocator, ais, tree, align_info.node, Space.None);
619
620 if (align_info.bit_range) |bit_range| {
621 const colon1 = tree.prevToken(bit_range.start.firstToken());
622 const colon2 = tree.prevToken(bit_range.end.firstToken());
623
624 try renderToken(tree, ais, colon1, Space.None); // :
625 try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
626 try renderToken(tree, ais, colon2, Space.None); // :
627 try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
628
629 const rparen_token = tree.nextToken(bit_range.end.lastToken());
630 try renderToken(tree, ais, rparen_token, Space.Space); // )
631 } else {
632 const rparen_token = tree.nextToken(align_info.node.lastToken());
633 try renderToken(tree, ais, rparen_token, Space.Space); // )
634 }
635 }
636 if (ptr_type.ptr_info.const_token) |const_token| {
637 try renderToken(tree, ais, const_token, Space.Space); // const
638 }
639 if (ptr_type.ptr_info.volatile_token) |volatile_token| {
640 try renderToken(tree, ais, volatile_token, Space.Space); // volatile
641 }
642 return renderExpression(allocator, ais, tree, ptr_type.rhs, space);
643 },
644
645 .SliceType => {
646 const slice_type = @fieldParentPtr(ast.Node.SliceType, "base", base);
647 try renderToken(tree, ais, slice_type.op_token, Space.None); // [
648 if (slice_type.ptr_info.sentinel) |sentinel| {
649 const colon_token = tree.prevToken(sentinel.firstToken());
650 try renderToken(tree, ais, colon_token, Space.None); // :
651 try renderExpression(allocator, ais, tree, sentinel, Space.None);
652 try renderToken(tree, ais, tree.nextToken(sentinel.lastToken()), Space.None); // ]
653 } else {
654 try renderToken(tree, ais, tree.nextToken(slice_type.op_token), Space.None); // ]
655 }
656
657 if (slice_type.ptr_info.allowzero_token) |allowzero_token| {
658 try renderToken(tree, ais, allowzero_token, Space.Space); // allowzero
659 }
660 if (slice_type.ptr_info.align_info) |align_info| {
661 const lparen_token = tree.prevToken(align_info.node.firstToken());
662 const align_token = tree.prevToken(lparen_token);
663
664 try renderToken(tree, ais, align_token, Space.None); // align
665 try renderToken(tree, ais, lparen_token, Space.None); // (
666
667 try renderExpression(allocator, ais, tree, align_info.node, Space.None);
668
669 if (align_info.bit_range) |bit_range| {
670 const colon1 = tree.prevToken(bit_range.start.firstToken());
671 const colon2 = tree.prevToken(bit_range.end.firstToken());
672
673 try renderToken(tree, ais, colon1, Space.None); // :
674 try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
675 try renderToken(tree, ais, colon2, Space.None); // :
676 try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
677
678 const rparen_token = tree.nextToken(bit_range.end.lastToken());
679 try renderToken(tree, ais, rparen_token, Space.Space); // )
680 } else {
681 const rparen_token = tree.nextToken(align_info.node.lastToken());
682 try renderToken(tree, ais, rparen_token, Space.Space); // )
683 }
684 }
685 if (slice_type.ptr_info.const_token) |const_token| {
686 try renderToken(tree, ais, const_token, Space.Space);
687 }
688 if (slice_type.ptr_info.volatile_token) |volatile_token| {
689 try renderToken(tree, ais, volatile_token, Space.Space);
690 }
691 return renderExpression(allocator, ais, tree, slice_type.rhs, space);
692 },
693
694 .ArrayInitializer, .ArrayInitializerDot => {
695 var rtoken: ast.TokenIndex = undefined;
696 var exprs: []*ast.Node = undefined;
697 const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) {
698 .ArrayInitializerDot => blk: {
699 const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base);
700 rtoken = casted.rtoken;
701 exprs = casted.list();
702 break :blk .{ .dot = casted.dot };
703 },
704 .ArrayInitializer => blk: {
705 const casted = @fieldParentPtr(ast.Node.ArrayInitializer, "base", base);
706 rtoken = casted.rtoken;
707 exprs = casted.list();
708 break :blk .{ .node = casted.lhs };
709 },
710 else => unreachable,
711 };
712
713 const lbrace = switch (lhs) {
714 .dot => |dot| tree.nextToken(dot),
715 .node => |node| tree.nextToken(node.lastToken()),
716 };
717
718 switch (lhs) {
719 .dot => |dot| try renderToken(tree, ais, dot, Space.None),
720 .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
721 }
722
723 if (exprs.len == 0) {
724 try renderToken(tree, ais, lbrace, Space.None);
725 return renderToken(tree, ais, rtoken, space);
726 }
727
728 if (exprs.len == 1 and exprs[0].tag != .MultilineStringLiteral and tree.token_ids[exprs[0].*.lastToken() + 1] == .RBrace) {
729 const expr = exprs[0];
730
731 try renderToken(tree, ais, lbrace, Space.None);
732 try renderExpression(allocator, ais, tree, expr, Space.None);
733 return renderToken(tree, ais, rtoken, space);
734 }
735
736 // scan to find row size
737 if (rowSize(tree, exprs, rtoken) != null) {
738 {
739 ais.pushIndentNextLine();
740 defer ais.popIndent();
741 try renderToken(tree, ais, lbrace, Space.Newline);
742
743 var expr_index: usize = 0;
744 while (rowSize(tree, exprs[expr_index..], rtoken)) |row_size| {
745 const row_exprs = exprs[expr_index..];
746 // A place to store the width of each expression and its column's maximum
747 var widths = try allocator.alloc(usize, row_exprs.len + row_size);
748 defer allocator.free(widths);
749 mem.set(usize, widths, 0);
750
751 var expr_newlines = try allocator.alloc(bool, row_exprs.len);
752 defer allocator.free(expr_newlines);
753 mem.set(bool, expr_newlines, false);
754
755 var expr_widths = widths[0 .. widths.len - row_size];
756 var column_widths = widths[widths.len - row_size ..];
757
758 // Find next row with trailing comment (if any) to end the current section
759 var section_end = sec_end: {
760 var this_line_first_expr: usize = 0;
761 var this_line_size = rowSize(tree, row_exprs, rtoken);
762 for (row_exprs) |expr, i| {
763 // Ignore comment on first line of this section
764 if (i == 0 or tree.tokensOnSameLine(row_exprs[0].firstToken(), expr.lastToken())) continue;
765 // Track start of line containing comment
766 if (!tree.tokensOnSameLine(row_exprs[this_line_first_expr].firstToken(), expr.lastToken())) {
767 this_line_first_expr = i;
768 this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rtoken);
769 }
770
771 const maybe_comma = expr.lastToken() + 1;
772 const maybe_comment = expr.lastToken() + 2;
773 if (maybe_comment < tree.token_ids.len) {
774 if (tree.token_ids[maybe_comma] == .Comma and
775 tree.token_ids[maybe_comment] == .LineComment and
776 tree.tokensOnSameLine(expr.lastToken(), maybe_comment))
777 {
778 var comment_token_loc = tree.token_locs[maybe_comment];
779 const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2;
780 if (!comment_is_empty) {
781 // Found row ending in comment
782 break :sec_end i - this_line_size.? + 1;
783 }
784 }
785 }
786 }
787 break :sec_end row_exprs.len;
788 };
789 expr_index += section_end;
790
791 const section_exprs = row_exprs[0..section_end];
792
793 // Null stream for counting the printed length of each expression
794 var line_find_stream = std.io.findByteWriter('\n', std.io.null_writer);
795 var counting_stream = std.io.countingWriter(line_find_stream.writer());
796 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer());
797
798 // Calculate size of columns in current section
799 var column_counter: usize = 0;
800 var single_line = true;
801 for (section_exprs) |expr, i| {
802 if (i + 1 < section_exprs.len) {
803 counting_stream.bytes_written = 0;
804 line_find_stream.byte_found = false;
805 try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
806 const width = @intCast(usize, counting_stream.bytes_written);
807 expr_widths[i] = width;
808 expr_newlines[i] = line_find_stream.byte_found;
809
810 if (!line_find_stream.byte_found) {
811 const column = column_counter % row_size;
812 column_widths[column] = std.math.max(column_widths[column], width);
813
814 const expr_last_token = expr.*.lastToken() + 1;
815 const next_expr = section_exprs[i + 1];
816 const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, next_expr.*.firstToken());
817
818 column_counter += 1;
819
820 if (loc.line != 0) single_line = false;
821 } else {
822 single_line = false;
823 column_counter = 0;
824 }
825 } else {
826 counting_stream.bytes_written = 0;
827 try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
828 const width = @intCast(usize, counting_stream.bytes_written);
829 expr_widths[i] = width;
830 expr_newlines[i] = line_find_stream.byte_found;
831
832 if (!line_find_stream.byte_found) {
833 const column = column_counter % row_size;
834 column_widths[column] = std.math.max(column_widths[column], width);
835 }
836 break;
837 }
838 }
839
840 // Render exprs in current section
841 column_counter = 0;
842 var last_col_index: usize = row_size - 1;
843 for (section_exprs) |expr, i| {
844 if (i + 1 < section_exprs.len) {
845 const next_expr = section_exprs[i + 1];
846 try renderExpression(allocator, ais, tree, expr, Space.None);
847
848 const comma = tree.nextToken(expr.*.lastToken());
849
850 if (column_counter != last_col_index) {
851 if (!expr_newlines[i] and !expr_newlines[i + 1]) {
852 // Neither the current or next expression is multiline
853 try renderToken(tree, ais, comma, Space.Space); // ,
854 assert(column_widths[column_counter % row_size] >= expr_widths[i]);
855 const padding = column_widths[column_counter % row_size] - expr_widths[i];
856 try ais.writer().writeByteNTimes(' ', padding);
857
858 column_counter += 1;
859 continue;
860 }
861 }
862 if (single_line and row_size != 1) {
863 try renderToken(tree, ais, comma, Space.Space); // ,
864 continue;
865 }
866
867 column_counter = 0;
868 try renderToken(tree, ais, comma, Space.Newline); // ,
869 try renderExtraNewline(tree, ais, next_expr);
870 } else {
871 const maybe_comma = tree.nextToken(expr.*.lastToken());
872 if (tree.token_ids[maybe_comma] == .Comma) {
873 try renderExpression(allocator, ais, tree, expr, Space.None); // ,
874 try renderToken(tree, ais, maybe_comma, Space.Newline); // ,
875 } else {
876 try renderExpression(allocator, ais, tree, expr, Space.Comma); // ,
877 }
878 }
879 }
880
881 if (expr_index == exprs.len) {
882 break;
883 }
884 }
885 }
886
887 return renderToken(tree, ais, rtoken, space);
888 }
889
890 // Single line
891 try renderToken(tree, ais, lbrace, Space.Space);
892 for (exprs) |expr, i| {
893 if (i + 1 < exprs.len) {
894 const next_expr = exprs[i + 1];
895 try renderExpression(allocator, ais, tree, expr, Space.None);
896 const comma = tree.nextToken(expr.*.lastToken());
897 try renderToken(tree, ais, comma, Space.Space); // ,
898 } else {
899 try renderExpression(allocator, ais, tree, expr, Space.Space);
900 }
901 }
902
903 return renderToken(tree, ais, rtoken, space);
904 },
905
906 .StructInitializer, .StructInitializerDot => {
907 var rtoken: ast.TokenIndex = undefined;
908 var field_inits: []*ast.Node = undefined;
909 const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) {
910 .StructInitializerDot => blk: {
911 const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base);
912 rtoken = casted.rtoken;
913 field_inits = casted.list();
914 break :blk .{ .dot = casted.dot };
915 },
916 .StructInitializer => blk: {
917 const casted = @fieldParentPtr(ast.Node.StructInitializer, "base", base);
918 rtoken = casted.rtoken;
919 field_inits = casted.list();
920 break :blk .{ .node = casted.lhs };
921 },
922 else => unreachable,
923 };
924
925 const lbrace = switch (lhs) {
926 .dot => |dot| tree.nextToken(dot),
927 .node => |node| tree.nextToken(node.lastToken()),
928 };
929
930 if (field_inits.len == 0) {
931 switch (lhs) {
932 .dot => |dot| try renderToken(tree, ais, dot, Space.None),
933 .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
934 }
935
936 {
937 ais.pushIndentNextLine();
938 defer ais.popIndent();
939 try renderToken(tree, ais, lbrace, Space.None);
940 }
941
942 return renderToken(tree, ais, rtoken, space);
943 }
944
945 const src_has_trailing_comma = blk: {
946 const maybe_comma = tree.prevToken(rtoken);
947 break :blk tree.token_ids[maybe_comma] == .Comma;
948 };
949
950 const src_same_line = blk: {
951 const loc = tree.tokenLocation(tree.token_locs[lbrace].end, rtoken);
952 break :blk loc.line == 0;
953 };
954
955 const expr_outputs_one_line = blk: {
956 // render field expressions until a LF is found
957 for (field_inits) |field_init| {
958 var find_stream = std.io.findByteWriter('\n', std.io.null_writer);
959 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, find_stream.writer());
960
961 try renderExpression(allocator, &auto_indenting_stream, tree, field_init, Space.None);
962 if (find_stream.byte_found) break :blk false;
963 }
964 break :blk true;
965 };
966
967 if (field_inits.len == 1) blk: {
968 if (field_inits[0].cast(ast.Node.FieldInitializer)) |field_init| {
969 switch (field_init.expr.tag) {
970 .StructInitializer,
971 .StructInitializerDot,
972 => break :blk,
973 else => {},
974 }
975 }
976
977 // if the expression outputs to multiline, make this struct multiline
978 if (!expr_outputs_one_line or src_has_trailing_comma) {
979 break :blk;
980 }
981
982 switch (lhs) {
983 .dot => |dot| try renderToken(tree, ais, dot, Space.None),
984 .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
985 }
986 try renderToken(tree, ais, lbrace, Space.Space);
987 try renderExpression(allocator, ais, tree, field_inits[0], Space.Space);
988 return renderToken(tree, ais, rtoken, space);
989 }
990
991 if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
992 // render all on one line, no trailing comma
993 switch (lhs) {
994 .dot => |dot| try renderToken(tree, ais, dot, Space.None),
995 .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
996 }
997 try renderToken(tree, ais, lbrace, Space.Space);
998
999 for (field_inits) |field_init, i| {
1000 if (i + 1 < field_inits.len) {
1001 try renderExpression(allocator, ais, tree, field_init, Space.None);
1002
1003 const comma = tree.nextToken(field_init.lastToken());
1004 try renderToken(tree, ais, comma, Space.Space);
1005 } else {
1006 try renderExpression(allocator, ais, tree, field_init, Space.Space);
1007 }
1008 }
1009
1010 return renderToken(tree, ais, rtoken, space);
1011 }
1012
1013 {
1014 switch (lhs) {
1015 .dot => |dot| try renderToken(tree, ais, dot, Space.None),
1016 .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
1017 }
1018
1019 ais.pushIndentNextLine();
1020 defer ais.popIndent();
1021
1022 try renderToken(tree, ais, lbrace, Space.Newline);
1023
1024 for (field_inits) |field_init, i| {
1025 if (i + 1 < field_inits.len) {
1026 const next_field_init = field_inits[i + 1];
1027 try renderExpression(allocator, ais, tree, field_init, Space.None);
1028
1029 const comma = tree.nextToken(field_init.lastToken());
1030 try renderToken(tree, ais, comma, Space.Newline);
1031
1032 try renderExtraNewline(tree, ais, next_field_init);
1033 } else {
1034 try renderExpression(allocator, ais, tree, field_init, Space.Comma);
1035 }
1036 }
1037 }
1038
1039 return renderToken(tree, ais, rtoken, space);
1040 },
1041
1042 .Call => {
1043 const call = @fieldParentPtr(ast.Node.Call, "base", base);
1044 if (call.async_token) |async_token| {
1045 try renderToken(tree, ais, async_token, Space.Space);
1046 }
1047
1048 try renderExpression(allocator, ais, tree, call.lhs, Space.None);
1049
1050 const lparen = tree.nextToken(call.lhs.lastToken());
1051
1052 if (call.params_len == 0) {
1053 try renderToken(tree, ais, lparen, Space.None);
1054 return renderToken(tree, ais, call.rtoken, space);
1055 }
1056
1057 const src_has_trailing_comma = blk: {
1058 const maybe_comma = tree.prevToken(call.rtoken);
1059 break :blk tree.token_ids[maybe_comma] == .Comma;
1060 };
1061
1062 if (src_has_trailing_comma) {
1063 {
1064 ais.pushIndent();
1065 defer ais.popIndent();
1066
1067 try renderToken(tree, ais, lparen, Space.Newline); // (
1068 const params = call.params();
1069 for (params) |param_node, i| {
1070 if (i + 1 < params.len) {
1071 const next_node = params[i + 1];
1072 try renderExpression(allocator, ais, tree, param_node, Space.None);
1073
1074 // Unindent the comma for multiline string literals
1075 const maybe_multiline_string = param_node.firstToken();
1076 const is_multiline_string = tree.token_ids[maybe_multiline_string] == .MultilineStringLiteralLine;
1077 if (is_multiline_string) ais.popIndent();
1078 defer if (is_multiline_string) ais.pushIndent();
1079
1080 const comma = tree.nextToken(param_node.lastToken());
1081 try renderToken(tree, ais, comma, Space.Newline); // ,
1082 try renderExtraNewline(tree, ais, next_node);
1083 } else {
1084 try renderExpression(allocator, ais, tree, param_node, Space.Comma);
1085 }
1086 }
1087 }
1088 return renderToken(tree, ais, call.rtoken, space);
1089 }
1090
1091 try renderToken(tree, ais, lparen, Space.None); // (
1092
1093 const params = call.params();
1094 for (params) |param_node, i| {
1095 const maybe_comment = param_node.firstToken() - 1;
1096 const maybe_multiline_string = param_node.firstToken();
1097 if (tree.token_ids[maybe_multiline_string] == .MultilineStringLiteralLine or tree.token_ids[maybe_comment] == .LineComment) {
1098 ais.pushIndentOneShot();
1099 }
1100
1101 try renderExpression(allocator, ais, tree, param_node, Space.None);
1102
1103 if (i + 1 < params.len) {
1104 const comma = tree.nextToken(param_node.lastToken());
1105 try renderToken(tree, ais, comma, Space.Space);
1106 }
1107 }
1108 return renderToken(tree, ais, call.rtoken, space); // )
1109 },
1110
1111 .ArrayAccess => {
1112 const suffix_op = base.castTag(.ArrayAccess).?;
1113
1114 const lbracket = tree.nextToken(suffix_op.lhs.lastToken());
1115 const rbracket = tree.nextToken(suffix_op.index_expr.lastToken());
1116
1117 try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1118 try renderToken(tree, ais, lbracket, Space.None); // [
1119
1120 const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment;
1121 const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment;
1122 {
1123 const new_space = if (ends_with_comment) Space.Newline else Space.None;
1124
1125 ais.pushIndent();
1126 defer ais.popIndent();
1127 try renderExpression(allocator, ais, tree, suffix_op.index_expr, new_space);
1128 }
1129 if (starts_with_comment) try ais.maybeInsertNewline();
1130 return renderToken(tree, ais, rbracket, space); // ]
1131 },
1132
1133 .Slice => {
1134 const suffix_op = base.castTag(.Slice).?;
1135 try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1136
1137 const lbracket = tree.prevToken(suffix_op.start.firstToken());
1138 const dotdot = tree.nextToken(suffix_op.start.lastToken());
1139
1140 const after_start_space_bool = nodeCausesSliceOpSpace(suffix_op.start) or
1141 (if (suffix_op.end) |end| nodeCausesSliceOpSpace(end) else false);
1142 const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
1143 const after_op_space = if (suffix_op.end != null) after_start_space else Space.None;
1144
1145 try renderToken(tree, ais, lbracket, Space.None); // [
1146 try renderExpression(allocator, ais, tree, suffix_op.start, after_start_space);
1147 try renderToken(tree, ais, dotdot, after_op_space); // ..
1148 if (suffix_op.end) |end| {
1149 const after_end_space = if (suffix_op.sentinel != null) Space.Space else Space.None;
1150 try renderExpression(allocator, ais, tree, end, after_end_space);
1151 }
1152 if (suffix_op.sentinel) |sentinel| {
1153 const colon = tree.prevToken(sentinel.firstToken());
1154 try renderToken(tree, ais, colon, Space.None); // :
1155 try renderExpression(allocator, ais, tree, sentinel, Space.None);
1156 }
1157 return renderToken(tree, ais, suffix_op.rtoken, space); // ]
1158 },
1159
1160 .Deref => {
1161 const suffix_op = base.castTag(.Deref).?;
1162
1163 try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1164 return renderToken(tree, ais, suffix_op.rtoken, space); // .*
1165 },
1166 .UnwrapOptional => {
1167 const suffix_op = base.castTag(.UnwrapOptional).?;
1168
1169 try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1170 try renderToken(tree, ais, tree.prevToken(suffix_op.rtoken), Space.None); // .
1171 return renderToken(tree, ais, suffix_op.rtoken, space); // ?
1172 },
1173
1174 .Break => {
1175 const flow_expr = base.castTag(.Break).?;
1176 const maybe_rhs = flow_expr.getRHS();
1177 const maybe_label = flow_expr.getLabel();
1178
1179 if (maybe_label == null and maybe_rhs == null) {
1180 return renderToken(tree, ais, flow_expr.ltoken, space); // break
1181 }
1182
1183 try renderToken(tree, ais, flow_expr.ltoken, Space.Space); // break
1184 if (maybe_label) |label| {
1185 const colon = tree.nextToken(flow_expr.ltoken);
1186 try renderToken(tree, ais, colon, Space.None); // :
1187
1188 if (maybe_rhs == null) {
1189 return renderToken(tree, ais, label, space); // label
1190 }
1191 try renderToken(tree, ais, label, Space.Space); // label
1192 }
1193 return renderExpression(allocator, ais, tree, maybe_rhs.?, space);
1194 },
1195
1196 .Continue => {
1197 const flow_expr = base.castTag(.Continue).?;
1198 if (flow_expr.getLabel()) |label| {
1199 try renderToken(tree, ais, flow_expr.ltoken, Space.Space); // continue
1200 const colon = tree.nextToken(flow_expr.ltoken);
1201 try renderToken(tree, ais, colon, Space.None); // :
1202 return renderToken(tree, ais, label, space); // label
1203 } else {
1204 return renderToken(tree, ais, flow_expr.ltoken, space); // continue
1205 }
1206 },
1207
1208 .Return => {
1209 const flow_expr = base.castTag(.Return).?;
1210 if (flow_expr.getRHS()) |rhs| {
1211 try renderToken(tree, ais, flow_expr.ltoken, Space.Space);
1212 return renderExpression(allocator, ais, tree, rhs, space);
1213 } else {
1214 return renderToken(tree, ais, flow_expr.ltoken, space);
1215 }
1216 },
1217
1218 .Payload => {
1219 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
1220
1221 try renderToken(tree, ais, payload.lpipe, Space.None);
1222 try renderExpression(allocator, ais, tree, payload.error_symbol, Space.None);
1223 return renderToken(tree, ais, payload.rpipe, space);
1224 },
1225
1226 .PointerPayload => {
1227 const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
1228
1229 try renderToken(tree, ais, payload.lpipe, Space.None);
1230 if (payload.ptr_token) |ptr_token| {
1231 try renderToken(tree, ais, ptr_token, Space.None);
1232 }
1233 try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
1234 return renderToken(tree, ais, payload.rpipe, space);
1235 },
1236
1237 .PointerIndexPayload => {
1238 const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
1239
1240 try renderToken(tree, ais, payload.lpipe, Space.None);
1241 if (payload.ptr_token) |ptr_token| {
1242 try renderToken(tree, ais, ptr_token, Space.None);
1243 }
1244 try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
1245
1246 if (payload.index_symbol) |index_symbol| {
1247 const comma = tree.nextToken(payload.value_symbol.lastToken());
1248
1249 try renderToken(tree, ais, comma, Space.Space);
1250 try renderExpression(allocator, ais, tree, index_symbol, Space.None);
1251 }
1252
1253 return renderToken(tree, ais, payload.rpipe, space);
1254 },
1255
1256 .GroupedExpression => {
1257 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
1258
1259 try renderToken(tree, ais, grouped_expr.lparen, Space.None);
1260 {
1261 ais.pushIndentOneShot();
1262 try renderExpression(allocator, ais, tree, grouped_expr.expr, Space.None);
1263 }
1264 return renderToken(tree, ais, grouped_expr.rparen, space);
1265 },
1266
1267 .FieldInitializer => {
1268 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
1269
1270 try renderToken(tree, ais, field_init.period_token, Space.None); // .
1271 try renderToken(tree, ais, field_init.name_token, Space.Space); // name
1272 try renderToken(tree, ais, tree.nextToken(field_init.name_token), Space.Space); // =
1273 return renderExpression(allocator, ais, tree, field_init.expr, space);
1274 },
1275
1276 .ContainerDecl => {
1277 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
1278
1279 if (container_decl.layout_token) |layout_token| {
1280 try renderToken(tree, ais, layout_token, Space.Space);
1281 }
1282
1283 switch (container_decl.init_arg_expr) {
1284 .None => {
1285 try renderToken(tree, ais, container_decl.kind_token, Space.Space); // union
1286 },
1287 .Enum => |enum_tag_type| {
1288 try renderToken(tree, ais, container_decl.kind_token, Space.None); // union
1289
1290 const lparen = tree.nextToken(container_decl.kind_token);
1291 const enum_token = tree.nextToken(lparen);
1292
1293 try renderToken(tree, ais, lparen, Space.None); // (
1294 try renderToken(tree, ais, enum_token, Space.None); // enum
1295
1296 if (enum_tag_type) |expr| {
1297 try renderToken(tree, ais, tree.nextToken(enum_token), Space.None); // (
1298 try renderExpression(allocator, ais, tree, expr, Space.None);
1299
1300 const rparen = tree.nextToken(expr.lastToken());
1301 try renderToken(tree, ais, rparen, Space.None); // )
1302 try renderToken(tree, ais, tree.nextToken(rparen), Space.Space); // )
1303 } else {
1304 try renderToken(tree, ais, tree.nextToken(enum_token), Space.Space); // )
1305 }
1306 },
1307 .Type => |type_expr| {
1308 try renderToken(tree, ais, container_decl.kind_token, Space.None); // union
1309
1310 const lparen = tree.nextToken(container_decl.kind_token);
1311 const rparen = tree.nextToken(type_expr.lastToken());
1312
1313 try renderToken(tree, ais, lparen, Space.None); // (
1314 try renderExpression(allocator, ais, tree, type_expr, Space.None);
1315 try renderToken(tree, ais, rparen, Space.Space); // )
1316 },
1317 }
1318
1319 if (container_decl.fields_and_decls_len == 0) {
1320 {
1321 ais.pushIndentNextLine();
1322 defer ais.popIndent();
1323 try renderToken(tree, ais, container_decl.lbrace_token, Space.None); // {
1324 }
1325 return renderToken(tree, ais, container_decl.rbrace_token, space); // }
1326 }
1327
1328 const src_has_trailing_comma = blk: {
1329 var maybe_comma = tree.prevToken(container_decl.lastToken());
1330 // Doc comments for a field may also appear after the comma, eg.
1331 // field_name: T, // comment attached to field_name
1332 if (tree.token_ids[maybe_comma] == .DocComment)
1333 maybe_comma = tree.prevToken(maybe_comma);
1334 break :blk tree.token_ids[maybe_comma] == .Comma;
1335 };
1336
1337 const fields_and_decls = container_decl.fieldsAndDecls();
1338
1339 // Check if the first declaration and the { are on the same line
1340 const src_has_newline = !tree.tokensOnSameLine(
1341 container_decl.lbrace_token,
1342 fields_and_decls[0].firstToken(),
1343 );
1344
1345 // We can only print all the elements in-line if all the
1346 // declarations inside are fields
1347 const src_has_only_fields = blk: {
1348 for (fields_and_decls) |decl| {
1349 if (decl.tag != .ContainerField) break :blk false;
1350 }
1351 break :blk true;
1352 };
1353
1354 if (src_has_trailing_comma or !src_has_only_fields) {
1355 // One declaration per line
1356 ais.pushIndentNextLine();
1357 defer ais.popIndent();
1358 try renderToken(tree, ais, container_decl.lbrace_token, .Newline); // {
1359
1360 for (fields_and_decls) |decl, i| {
1361 try renderContainerDecl(allocator, ais, tree, decl, .Newline);
1362
1363 if (i + 1 < fields_and_decls.len) {
1364 try renderExtraNewline(tree, ais, fields_and_decls[i + 1]);
1365 }
1366 }
1367 } else if (src_has_newline) {
1368 // All the declarations on the same line, but place the items on
1369 // their own line
1370 try renderToken(tree, ais, container_decl.lbrace_token, .Newline); // {
1371
1372 ais.pushIndent();
1373 defer ais.popIndent();
1374
1375 for (fields_and_decls) |decl, i| {
1376 const space_after_decl: Space = if (i + 1 >= fields_and_decls.len) .Newline else .Space;
1377 try renderContainerDecl(allocator, ais, tree, decl, space_after_decl);
1378 }
1379 } else {
1380 // All the declarations on the same line
1381 try renderToken(tree, ais, container_decl.lbrace_token, .Space); // {
1382
1383 for (fields_and_decls) |decl| {
1384 try renderContainerDecl(allocator, ais, tree, decl, .Space);
1385 }
1386 }
1387
1388 return renderToken(tree, ais, container_decl.rbrace_token, space); // }
1389 },
1390
1391 .ErrorSetDecl => {
1392 const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
1393
1394 const lbrace = tree.nextToken(err_set_decl.error_token);
1395
1396 if (err_set_decl.decls_len == 0) {
1397 try renderToken(tree, ais, err_set_decl.error_token, Space.None);
1398 try renderToken(tree, ais, lbrace, Space.None);
1399 return renderToken(tree, ais, err_set_decl.rbrace_token, space);
1400 }
1401
1402 if (err_set_decl.decls_len == 1) blk: {
1403 const node = err_set_decl.decls()[0];
1404
1405 // if there are any doc comments or same line comments
1406 // don't try to put it all on one line
1407 if (node.cast(ast.Node.ErrorTag)) |tag| {
1408 if (tag.doc_comments != null) break :blk;
1409 } else {
1410 break :blk;
1411 }
1412
1413 try renderToken(tree, ais, err_set_decl.error_token, Space.None); // error
1414 try renderToken(tree, ais, lbrace, Space.None); // {
1415 try renderExpression(allocator, ais, tree, node, Space.None);
1416 return renderToken(tree, ais, err_set_decl.rbrace_token, space); // }
1417 }
1418
1419 try renderToken(tree, ais, err_set_decl.error_token, Space.None); // error
1420
1421 const src_has_trailing_comma = blk: {
1422 const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
1423 break :blk tree.token_ids[maybe_comma] == .Comma;
1424 };
1425
1426 if (src_has_trailing_comma) {
1427 {
1428 ais.pushIndent();
1429 defer ais.popIndent();
1430
1431 try renderToken(tree, ais, lbrace, Space.Newline); // {
1432 const decls = err_set_decl.decls();
1433 for (decls) |node, i| {
1434 if (i + 1 < decls.len) {
1435 try renderExpression(allocator, ais, tree, node, Space.None);
1436 try renderToken(tree, ais, tree.nextToken(node.lastToken()), Space.Newline); // ,
1437
1438 try renderExtraNewline(tree, ais, decls[i + 1]);
1439 } else {
1440 try renderExpression(allocator, ais, tree, node, Space.Comma);
1441 }
1442 }
1443 }
1444
1445 return renderToken(tree, ais, err_set_decl.rbrace_token, space); // }
1446 } else {
1447 try renderToken(tree, ais, lbrace, Space.Space); // {
1448
1449 const decls = err_set_decl.decls();
1450 for (decls) |node, i| {
1451 if (i + 1 < decls.len) {
1452 try renderExpression(allocator, ais, tree, node, Space.None);
1453
1454 const comma_token = tree.nextToken(node.lastToken());
1455 assert(tree.token_ids[comma_token] == .Comma);
1456 try renderToken(tree, ais, comma_token, Space.Space); // ,
1457 try renderExtraNewline(tree, ais, decls[i + 1]);
1458 } else {
1459 try renderExpression(allocator, ais, tree, node, Space.Space);
1460 }
1461 }
1462
1463 return renderToken(tree, ais, err_set_decl.rbrace_token, space); // }
1464 }
1465 },
1466
1467 .ErrorTag => {
1468 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
1469
1470 try renderDocComments(tree, ais, tag, tag.doc_comments);
1471 return renderToken(tree, ais, tag.name_token, space); // name
1472 },
1473
1474 .MultilineStringLiteral => {
1475 const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
1476
1477 {
1478 const locked_indents = ais.lockOneShotIndent();
1479 defer {
1480 var i: u8 = 0;
1481 while (i < locked_indents) : (i += 1) ais.popIndent();
1482 }
1483 try ais.maybeInsertNewline();
1484
1485 for (multiline_str_literal.lines()) |t| try renderToken(tree, ais, t, Space.None);
1486 }
1487 },
1488
1489 .BuiltinCall => {
1490 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
1491
1492 // TODO remove after 0.7.0 release
1493 if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
1494 return ais.writer().writeAll("opaque {}");
1495
1496 // TODO remove after 0.7.0 release
1497 {
1498 const params = builtin_call.paramsConst();
1499 if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
1500 params.len == 1)
1501 {
1502 if (params[0].castTag(.EnumLiteral)) |enum_literal|
1503 if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
1504 return ais.writer().writeAll("opaque {}");
1505 }
1506 }
1507
1508 try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name
1509
1510 const src_params_trailing_comma = blk: {
1511 if (builtin_call.params_len == 0) break :blk false;
1512 const last_node = builtin_call.params()[builtin_call.params_len - 1];
1513 const maybe_comma = tree.nextToken(last_node.lastToken());
1514 break :blk tree.token_ids[maybe_comma] == .Comma;
1515 };
1516
1517 const lparen = tree.nextToken(builtin_call.builtin_token);
1518
1519 if (!src_params_trailing_comma) {
1520 try renderToken(tree, ais, lparen, Space.None); // (
1521
1522 // render all on one line, no trailing comma
1523 const params = builtin_call.params();
1524 for (params) |param_node, i| {
1525 const maybe_comment = param_node.firstToken() - 1;
1526 if (param_node.*.tag == .MultilineStringLiteral or tree.token_ids[maybe_comment] == .LineComment) {
1527 ais.pushIndentOneShot();
1528 }
1529 try renderExpression(allocator, ais, tree, param_node, Space.None);
1530
1531 if (i + 1 < params.len) {
1532 const comma_token = tree.nextToken(param_node.lastToken());
1533 try renderToken(tree, ais, comma_token, Space.Space); // ,
1534 }
1535 }
1536 } else {
1537 // one param per line
1538 ais.pushIndent();
1539 defer ais.popIndent();
1540 try renderToken(tree, ais, lparen, Space.Newline); // (
1541
1542 for (builtin_call.params()) |param_node| {
1543 try renderExpression(allocator, ais, tree, param_node, Space.Comma);
1544 }
1545 }
1546
1547 return renderToken(tree, ais, builtin_call.rparen_token, space); // )
1548 },
1549
1550 .FnProto => {
1551 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base);
1552
1553 if (fn_proto.getVisibToken()) |visib_token_index| {
1554 const visib_token = tree.token_ids[visib_token_index];
1555 assert(visib_token == .Keyword_pub or visib_token == .Keyword_export);
1556
1557 try renderToken(tree, ais, visib_token_index, Space.Space); // pub
1558 }
1559
1560 if (fn_proto.getExternExportInlineToken()) |extern_export_inline_token| {
1561 if (fn_proto.getIsExternPrototype() == null)
1562 try renderToken(tree, ais, extern_export_inline_token, Space.Space); // extern/export/inline
1563 }
1564
1565 if (fn_proto.getLibName()) |lib_name| {
1566 try renderExpression(allocator, ais, tree, lib_name, Space.Space);
1567 }
1568
1569 const lparen = if (fn_proto.getNameToken()) |name_token| blk: {
1570 try renderToken(tree, ais, fn_proto.fn_token, Space.Space); // fn
1571 try renderToken(tree, ais, name_token, Space.None); // name
1572 break :blk tree.nextToken(name_token);
1573 } else blk: {
1574 try renderToken(tree, ais, fn_proto.fn_token, Space.Space); // fn
1575 break :blk tree.nextToken(fn_proto.fn_token);
1576 };
1577 assert(tree.token_ids[lparen] == .LParen);
1578
1579 const rparen = tree.prevToken(
1580 // the first token for the annotation expressions is the left
1581 // parenthesis, hence the need for two prevToken
1582 if (fn_proto.getAlignExpr()) |align_expr|
1583 tree.prevToken(tree.prevToken(align_expr.firstToken()))
1584 else if (fn_proto.getSectionExpr()) |section_expr|
1585 tree.prevToken(tree.prevToken(section_expr.firstToken()))
1586 else if (fn_proto.getCallconvExpr()) |callconv_expr|
1587 tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
1588 else switch (fn_proto.return_type) {
1589 .Explicit => |node| node.firstToken(),
1590 .InferErrorSet => |node| tree.prevToken(node.firstToken()),
1591 .Invalid => unreachable,
1592 },
1593 );
1594 assert(tree.token_ids[rparen] == .RParen);
1595
1596 const src_params_trailing_comma = blk: {
1597 const maybe_comma = tree.token_ids[rparen - 1];
1598 break :blk maybe_comma == .Comma or maybe_comma == .LineComment;
1599 };
1600
1601 if (!src_params_trailing_comma) {
1602 try renderToken(tree, ais, lparen, Space.None); // (
1603
1604 // render all on one line, no trailing comma
1605 for (fn_proto.params()) |param_decl, i| {
1606 try renderParamDecl(allocator, ais, tree, param_decl, Space.None);
1607
1608 if (i + 1 < fn_proto.params_len or fn_proto.getVarArgsToken() != null) {
1609 const comma = tree.nextToken(param_decl.lastToken());
1610 try renderToken(tree, ais, comma, Space.Space); // ,
1611 }
1612 }
1613 if (fn_proto.getVarArgsToken()) |var_args_token| {
1614 try renderToken(tree, ais, var_args_token, Space.None);
1615 }
1616 } else {
1617 // one param per line
1618 ais.pushIndent();
1619 defer ais.popIndent();
1620 try renderToken(tree, ais, lparen, Space.Newline); // (
1621
1622 for (fn_proto.params()) |param_decl| {
1623 try renderParamDecl(allocator, ais, tree, param_decl, Space.Comma);
1624 }
1625 if (fn_proto.getVarArgsToken()) |var_args_token| {
1626 try renderToken(tree, ais, var_args_token, Space.Comma);
1627 }
1628 }
1629
1630 try renderToken(tree, ais, rparen, Space.Space); // )
1631
1632 if (fn_proto.getAlignExpr()) |align_expr| {
1633 const align_rparen = tree.nextToken(align_expr.lastToken());
1634 const align_lparen = tree.prevToken(align_expr.firstToken());
1635 const align_kw = tree.prevToken(align_lparen);
1636
1637 try renderToken(tree, ais, align_kw, Space.None); // align
1638 try renderToken(tree, ais, align_lparen, Space.None); // (
1639 try renderExpression(allocator, ais, tree, align_expr, Space.None);
1640 try renderToken(tree, ais, align_rparen, Space.Space); // )
1641 }
1642
1643 if (fn_proto.getSectionExpr()) |section_expr| {
1644 const section_rparen = tree.nextToken(section_expr.lastToken());
1645 const section_lparen = tree.prevToken(section_expr.firstToken());
1646 const section_kw = tree.prevToken(section_lparen);
1647
1648 try renderToken(tree, ais, section_kw, Space.None); // section
1649 try renderToken(tree, ais, section_lparen, Space.None); // (
1650 try renderExpression(allocator, ais, tree, section_expr, Space.None);
1651 try renderToken(tree, ais, section_rparen, Space.Space); // )
1652 }
1653
1654 if (fn_proto.getCallconvExpr()) |callconv_expr| {
1655 const callconv_rparen = tree.nextToken(callconv_expr.lastToken());
1656 const callconv_lparen = tree.prevToken(callconv_expr.firstToken());
1657 const callconv_kw = tree.prevToken(callconv_lparen);
1658
1659 try renderToken(tree, ais, callconv_kw, Space.None); // callconv
1660 try renderToken(tree, ais, callconv_lparen, Space.None); // (
1661 try renderExpression(allocator, ais, tree, callconv_expr, Space.None);
1662 try renderToken(tree, ais, callconv_rparen, Space.Space); // )
1663 } else if (fn_proto.getIsExternPrototype() != null) {
1664 try ais.writer().writeAll("callconv(.C) ");
1665 } else if (fn_proto.getIsAsync() != null) {
1666 try ais.writer().writeAll("callconv(.Async) ");
1667 }
1668
1669 switch (fn_proto.return_type) {
1670 .Explicit => |node| {
1671 return renderExpression(allocator, ais, tree, node, space);
1672 },
1673 .InferErrorSet => |node| {
1674 try renderToken(tree, ais, tree.prevToken(node.firstToken()), Space.None); // !
1675 return renderExpression(allocator, ais, tree, node, space);
1676 },
1677 .Invalid => unreachable,
1678 }
1679 },
1680
1681 .AnyFrameType => {
1682 const anyframe_type = @fieldParentPtr(ast.Node.AnyFrameType, "base", base);
1683
1684 if (anyframe_type.result) |result| {
1685 try renderToken(tree, ais, anyframe_type.anyframe_token, Space.None); // anyframe
1686 try renderToken(tree, ais, result.arrow_token, Space.None); // ->
1687 return renderExpression(allocator, ais, tree, result.return_type, space);
1688 } else {
1689 return renderToken(tree, ais, anyframe_type.anyframe_token, space); // anyframe
1690 }
1691 },
1692
1693 .DocComment => unreachable, // doc comments are attached to nodes
1694
1695 .Switch => {
1696 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
1697
1698 try renderToken(tree, ais, switch_node.switch_token, Space.Space); // switch
1699 try renderToken(tree, ais, tree.nextToken(switch_node.switch_token), Space.None); // (
1700
1701 const rparen = tree.nextToken(switch_node.expr.lastToken());
1702 const lbrace = tree.nextToken(rparen);
1703
1704 if (switch_node.cases_len == 0) {
1705 try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
1706 try renderToken(tree, ais, rparen, Space.Space); // )
1707 try renderToken(tree, ais, lbrace, Space.None); // {
1708 return renderToken(tree, ais, switch_node.rbrace, space); // }
1709 }
1710
1711 try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
1712 try renderToken(tree, ais, rparen, Space.Space); // )
1713
1714 {
1715 ais.pushIndentNextLine();
1716 defer ais.popIndent();
1717 try renderToken(tree, ais, lbrace, Space.Newline); // {
1718
1719 const cases = switch_node.cases();
1720 for (cases) |node, i| {
1721 try renderExpression(allocator, ais, tree, node, Space.Comma);
1722
1723 if (i + 1 < cases.len) {
1724 try renderExtraNewline(tree, ais, cases[i + 1]);
1725 }
1726 }
1727 }
1728
1729 return renderToken(tree, ais, switch_node.rbrace, space); // }
1730 },
1731
1732 .SwitchCase => {
1733 const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
1734
1735 assert(switch_case.items_len != 0);
1736 const src_has_trailing_comma = blk: {
1737 const last_node = switch_case.items()[switch_case.items_len - 1];
1738 const maybe_comma = tree.nextToken(last_node.lastToken());
1739 break :blk tree.token_ids[maybe_comma] == .Comma;
1740 };
1741
1742 if (switch_case.items_len == 1 or !src_has_trailing_comma) {
1743 const items = switch_case.items();
1744 for (items) |node, i| {
1745 if (i + 1 < items.len) {
1746 try renderExpression(allocator, ais, tree, node, Space.None);
1747
1748 const comma_token = tree.nextToken(node.lastToken());
1749 try renderToken(tree, ais, comma_token, Space.Space); // ,
1750 try renderExtraNewline(tree, ais, items[i + 1]);
1751 } else {
1752 try renderExpression(allocator, ais, tree, node, Space.Space);
1753 }
1754 }
1755 } else {
1756 const items = switch_case.items();
1757 for (items) |node, i| {
1758 if (i + 1 < items.len) {
1759 try renderExpression(allocator, ais, tree, node, Space.None);
1760
1761 const comma_token = tree.nextToken(node.lastToken());
1762 try renderToken(tree, ais, comma_token, Space.Newline); // ,
1763 try renderExtraNewline(tree, ais, items[i + 1]);
1764 } else {
1765 try renderExpression(allocator, ais, tree, node, Space.Comma);
1766 }
1767 }
1768 }
1769
1770 try renderToken(tree, ais, switch_case.arrow_token, Space.Space); // =>
1771
1772 if (switch_case.payload) |payload| {
1773 try renderExpression(allocator, ais, tree, payload, Space.Space);
1774 }
1775
1776 return renderExpression(allocator, ais, tree, switch_case.expr, space);
1777 },
1778 .SwitchElse => {
1779 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
1780 return renderToken(tree, ais, switch_else.token, space);
1781 },
1782 .Else => {
1783 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
1784
1785 const body_is_block = nodeIsBlock(else_node.body);
1786 const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
1787
1788 const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
1789 try renderToken(tree, ais, else_node.else_token, after_else_space);
1790
1791 if (else_node.payload) |payload| {
1792 const payload_space = if (same_line) Space.Space else Space.Newline;
1793 try renderExpression(allocator, ais, tree, payload, payload_space);
1794 }
1795
1796 if (same_line) {
1797 return renderExpression(allocator, ais, tree, else_node.body, space);
1798 } else {
1799 ais.pushIndent();
1800 defer ais.popIndent();
1801 return renderExpression(allocator, ais, tree, else_node.body, space);
1802 }
1803 },
1804
1805 .While => {
1806 const while_node = @fieldParentPtr(ast.Node.While, "base", base);
1807
1808 if (while_node.label) |label| {
1809 try renderToken(tree, ais, label, Space.None); // label
1810 try renderToken(tree, ais, tree.nextToken(label), Space.Space); // :
1811 }
1812
1813 if (while_node.inline_token) |inline_token| {
1814 try renderToken(tree, ais, inline_token, Space.Space); // inline
1815 }
1816
1817 try renderToken(tree, ais, while_node.while_token, Space.Space); // while
1818 try renderToken(tree, ais, tree.nextToken(while_node.while_token), Space.None); // (
1819 try renderExpression(allocator, ais, tree, while_node.condition, Space.None);
1820
1821 const cond_rparen = tree.nextToken(while_node.condition.lastToken());
1822
1823 const body_is_block = nodeIsBlock(while_node.body);
1824
1825 var block_start_space: Space = undefined;
1826 var after_body_space: Space = undefined;
1827
1828 if (body_is_block) {
1829 block_start_space = Space.BlockStart;
1830 after_body_space = if (while_node.@"else" == null) space else Space.SpaceOrOutdent;
1831 } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
1832 block_start_space = Space.Space;
1833 after_body_space = if (while_node.@"else" == null) space else Space.Space;
1834 } else {
1835 block_start_space = Space.Newline;
1836 after_body_space = if (while_node.@"else" == null) space else Space.Newline;
1837 }
1838
1839 {
1840 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
1841 try renderToken(tree, ais, cond_rparen, rparen_space); // )
1842 }
1843
1844 if (while_node.payload) |payload| {
1845 const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
1846 try renderExpression(allocator, ais, tree, payload, payload_space);
1847 }
1848
1849 if (while_node.continue_expr) |continue_expr| {
1850 const rparen = tree.nextToken(continue_expr.lastToken());
1851 const lparen = tree.prevToken(continue_expr.firstToken());
1852 const colon = tree.prevToken(lparen);
1853
1854 try renderToken(tree, ais, colon, Space.Space); // :
1855 try renderToken(tree, ais, lparen, Space.None); // (
1856
1857 try renderExpression(allocator, ais, tree, continue_expr, Space.None);
1858
1859 try renderToken(tree, ais, rparen, block_start_space); // )
1860 }
1861
1862 {
1863 if (!body_is_block) ais.pushIndent();
1864 defer if (!body_is_block) ais.popIndent();
1865 try renderExpression(allocator, ais, tree, while_node.body, after_body_space);
1866 }
186733
1868 if (while_node.@"else") |@"else"| {34/// Assumes there are no tokens in between start and end.
1869 return renderExpression(allocator, ais, tree, &@"else".base, space);35fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize, prefix: []const u8) Error!usize {
36 var index: usize = start;
37 var count: usize = 0;
38 while (true) {
39 // Scan forward to the next line comment, counting newlines.
40 const comment_start = mem.indexOf(u8, tree.source[index..end], "//") orelse return count;
41 const newline = mem.indexOfScalar(u8, tree.source[comment_start..end], '\n').?;
42 const untrimmed_comment = tree.source[comment_start..][0..newline];
43 const trimmed_comment = mem.trimRight(u8, untrimmed_comment, " \r\t");
44 if (count == 0) {
45 count += 1;
46 try ais.writer().writeAll(prefix);
47 } else {
48 // If another newline occurs between prev comment and this one
49 // we honor it, but not any additional ones.
50 if (mem.indexOfScalar(u8, tree.source[index..comment_start], '\n') != null) {
51 try ais.insertNewline();
1870 }52 }
1871 },53 }
54 try ais.writer().print("{s}\n", .{trimmed_comment});
55 index += comment_start + newline;
56 }
57}
187258
1873 .For => {59fn renderRoot(ais: *Ais, tree: ast.Tree) Error!void {
1874 const for_node = @fieldParentPtr(ast.Node.For, "base", base);60 // Render all the line comments at the beginning of the file.
61 const src_start: usize = if (mem.startsWith(u8, tree.source, "\xEF\xBB\xBF")) 3 else 0;
62 const comment_end_loc: usize = tree.tokens.items(.start)[0];
63 _ = try renderComments(ais, tree, src_start, comment_end_loc, "");
187564
1876 if (for_node.label) |label| {65 // Root is always index 0.
1877 try renderToken(tree, ais, label, Space.None); // label66 const nodes_data = tree.nodes.items(.data);
1878 try renderToken(tree, ais, tree.nextToken(label), Space.Space); // :67 const root_decls = tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs];
1879 }68 if (root_decls.len == 0) return;
188069
1881 if (for_node.inline_token) |inline_token| {70 for (root_decls) |decl| {
1882 try renderToken(tree, ais, inline_token, Space.Space); // inline71 try renderTopLevelDecl(ais, tree, decl);
1883 }72 }
73}
188474
1885 try renderToken(tree, ais, for_node.for_token, Space.Space); // for75fn renderExtraNewline(tree: ast.Tree, ais: *Ais, node: ast.Node.Index) Error!void {
1886 try renderToken(tree, ais, tree.nextToken(for_node.for_token), Space.None); // (76 return renderExtraNewlineToken(tree, ais, tree.firstToken(node));
1887 try renderExpression(allocator, ais, tree, for_node.array_expr, Space.None);77}
188878
1889 const rparen = tree.nextToken(for_node.array_expr.lastToken());79fn renderExtraNewlineToken(tree: ast.Tree, ais: *Ais, first_token: ast.TokenIndex) Error!void {
80 @panic("TODO implement renderExtraNewlineToken");
81 //var prev_token = first_token;
82 //if (prev_token == 0) return;
83 //const token_tags = tree.tokens.items(.tag);
84 //var newline_threshold: usize = 2;
85 //while (token_tags[prev_token - 1] == .DocComment) {
86 // if (tree.tokenLocation(tree.token_locs[prev_token - 1].end, prev_token).line == 1) {
87 // newline_threshold += 1;
88 // }
89 // prev_token -= 1;
90 //}
91 //const prev_token_end = tree.token_locs[prev_token - 1].end;
92 //const loc = tree.tokenLocation(prev_token_end, first_token);
93 //if (loc.line >= newline_threshold) {
94 // try ais.insertNewline();
95 //}
96}
189097
1891 const body_is_block = for_node.body.tag.isBlock();98fn renderTopLevelDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index) Error!void {
1892 const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());99 return renderContainerDecl(ais, tree, decl, .Newline);
1893 const body_on_same_line = body_is_block or src_one_line_to_body;100}
1894101
1895 try renderToken(tree, ais, rparen, Space.Space); // )102fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void {
103 switch (tree.nodes.items(.tag)[decl]) {
104 .UsingNamespace,
105 .FnProtoSimple,
106 .FnProtoSimpleMulti,
107 .FnProtoOne,
108 .FnProto,
109 .FnDecl,
110 .GlobalVarDecl,
111 .LocalVarDecl,
112 .SimpleVarDecl,
113 .AlignedVarDecl,
114 .TestDecl,
115 .ContainerFieldInit,
116 .ContainerFieldAlign,
117 .ContainerField,
118 => @panic("TODO implement renderContainerDecl"),
1896119
1897 const space_after_payload = if (body_on_same_line) Space.Space else Space.Newline;120 .Comptime => return renderExpression(ais, tree, decl, space),
1898 try renderExpression(allocator, ais, tree, for_node.payload, space_after_payload); // |x|
1899121
1900 const space_after_body = blk: {122 else => unreachable,
1901 if (for_node.@"else") |@"else"| {123 }
1902 const src_one_line_to_else = tree.tokensOnSameLine(rparen, @"else".firstToken());124 //switch (tag) {
1903 if (body_is_block or src_one_line_to_else) {125 // .FnProto => {
1904 break :blk Space.Space;126 // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
1905 } else {127
1906 break :blk Space.Newline;128 // try renderDocComments(tree, ais, fn_proto, fn_proto.getDocComments());
1907 }129
1908 } else {130 // if (fn_proto.getBodyNode()) |body_node| {
1909 break :blk space;131 // try renderExpression(allocator, ais, tree, decl, .Space);
1910 }132 // try renderExpression(allocator, ais, tree, body_node, space);
1911 };133 // } else {
134 // try renderExpression(allocator, ais, tree, decl, .None);
135 // try renderToken(ais, tree, tree.nextToken(decl.lastToken()), space);
136 // }
137 // },
138
139 // .Use => {
140 // const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
141
142 // if (use_decl.visib_token) |visib_token| {
143 // try renderToken(ais, tree, visib_token, .Space); // pub
144 // }
145 // try renderToken(ais, tree, use_decl.use_token, .Space); // usingnamespace
146 // try renderExpression(allocator, ais, tree, use_decl.expr, .None);
147 // try renderToken(ais, tree, use_decl.semicolon_token, space); // ;
148 // },
149
150 // .VarDecl => {
151 // const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
152
153 // try renderDocComments(tree, ais, var_decl, var_decl.getDocComments());
154 // try renderVarDecl(allocator, ais, tree, var_decl);
155 // },
156
157 // .TestDecl => {
158 // const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
159
160 // try renderDocComments(tree, ais, test_decl, test_decl.doc_comments);
161 // try renderToken(ais, tree, test_decl.test_token, .Space);
162 // if (test_decl.name) |name|
163 // try renderExpression(allocator, ais, tree, name, .Space);
164 // try renderExpression(allocator, ais, tree, test_decl.body_node, space);
165 // },
166
167 // .ContainerField => {
168 // const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
169
170 // try renderDocComments(tree, ais, field, field.doc_comments);
171 // if (field.comptime_token) |t| {
172 // try renderToken(ais, tree, t, .Space); // comptime
173 // }
174
175 // const src_has_trailing_comma = blk: {
176 // const maybe_comma = tree.nextToken(field.lastToken());
177 // break :blk tree.token_tags[maybe_comma] == .Comma;
178 // };
179
180 // // The trailing comma is emitted at the end, but if it's not present
181 // // we still have to respect the specified `space` parameter
182 // const last_token_space: Space = if (src_has_trailing_comma) .None else space;
183
184 // if (field.type_expr == null and field.value_expr == null) {
185 // try renderToken(ais, tree, field.name_token, last_token_space); // name
186 // } else if (field.type_expr != null and field.value_expr == null) {
187 // try renderToken(ais, tree, field.name_token, .None); // name
188 // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // :
189
190 // if (field.align_expr) |align_value_expr| {
191 // try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
192 // const lparen_token = tree.prevToken(align_value_expr.firstToken());
193 // const align_kw = tree.prevToken(lparen_token);
194 // const rparen_token = tree.nextToken(align_value_expr.lastToken());
195 // try renderToken(ais, tree, align_kw, .None); // align
196 // try renderToken(ais, tree, lparen_token, .None); // (
197 // try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
198 // try renderToken(ais, tree, rparen_token, last_token_space); // )
199 // } else {
200 // try renderExpression(allocator, ais, tree, field.type_expr.?, last_token_space); // type
201 // }
202 // } else if (field.type_expr == null and field.value_expr != null) {
203 // try renderToken(ais, tree, field.name_token, .Space); // name
204 // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // =
205 // try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
206 // } else {
207 // try renderToken(ais, tree, field.name_token, .None); // name
208 // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // :
209
210 // if (field.align_expr) |align_value_expr| {
211 // try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
212 // const lparen_token = tree.prevToken(align_value_expr.firstToken());
213 // const align_kw = tree.prevToken(lparen_token);
214 // const rparen_token = tree.nextToken(align_value_expr.lastToken());
215 // try renderToken(ais, tree, align_kw, .None); // align
216 // try renderToken(ais, tree, lparen_token, .None); // (
217 // try renderExpression(allocator, ais, tree, align_value_expr, .None); // alignment
218 // try renderToken(ais, tree, rparen_token, .Space); // )
219 // } else {
220 // try renderExpression(allocator, ais, tree, field.type_expr.?, .Space); // type
221 // }
222 // try renderToken(ais, tree, tree.prevToken(field.value_expr.?.firstToken()), .Space); // =
223 // try renderExpression(allocator, ais, tree, field.value_expr.?, last_token_space); // value
224 // }
225
226 // if (src_has_trailing_comma) {
227 // const comma = tree.nextToken(field.lastToken());
228 // try renderToken(ais, tree, comma, space);
229 // }
230 // },
231
232 // .DocComment => {
233 // const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl);
234 // const kind = tree.token_tags[comment.first_line];
235 // try renderToken(ais, tree, comment.first_line, .Newline);
236 // var tok_i = comment.first_line + 1;
237 // while (true) : (tok_i += 1) {
238 // const tok_id = tree.token_tags[tok_i];
239 // if (tok_id == kind) {
240 // try renderToken(ais, tree, tok_i, .Newline);
241 // } else if (tok_id == .LineComment) {
242 // continue;
243 // } else {
244 // break;
245 // }
246 // }
247 // },
248 // else => unreachable,
249 //}
250}
1912251
252fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {
253 const token_tags = tree.tokens.items(.tag);
254 const main_tokens = tree.nodes.items(.main_token);
255 switch (tree.nodes.items(.tag)[node]) {
256 //.Identifier,
257 //.IntegerLiteral,
258 //.FloatLiteral,
259 //.StringLiteral,
260 //.CharLiteral,
261 //.BoolLiteral,
262 //.NullLiteral,
263 //.Unreachable,
264 //.ErrorType,
265 //.UndefinedLiteral,
266 //=> {
267 // const casted_node = base.cast(ast.Node.OneToken).?;
268 // return renderToken(ais, tree, casted_node.token, space);
269 //},
270
271 //.AnyType => {
272 // const any_type = base.castTag(.AnyType).?;
273 // if (mem.eql(u8, tree.tokenSlice(any_type.token), "var")) {
274 // // TODO remove in next release cycle
275 // try ais.writer().writeAll("anytype");
276 // if (space == .Comma) try ais.writer().writeAll(",\n");
277 // return;
278 // }
279 // return renderToken(ais, tree, any_type.token, space);
280 //},
281 .Block => {
282 const lbrace = main_tokens[node];
283 if (token_tags[lbrace - 1] == .Colon and
284 token_tags[lbrace - 2] == .Identifier)
1913 {285 {
1914 if (!body_on_same_line) ais.pushIndent();286 try renderToken(ais, tree, lbrace - 2, .None);
1915 defer if (!body_on_same_line) ais.popIndent();287 try renderToken(ais, tree, lbrace - 1, .Space);
1916 try renderExpression(allocator, ais, tree, for_node.body, space_after_body); // { body }
1917 }
1918
1919 if (for_node.@"else") |@"else"| {
1920 return renderExpression(allocator, ais, tree, &@"else".base, space); // else
1921 }
1922 },
1923
1924 .If => {
1925 const if_node = @fieldParentPtr(ast.Node.If, "base", base);
1926
1927 const lparen = tree.nextToken(if_node.if_token);
1928 const rparen = tree.nextToken(if_node.condition.lastToken());
1929
1930 try renderToken(tree, ais, if_node.if_token, Space.Space); // if
1931 try renderToken(tree, ais, lparen, Space.None); // (
1932
1933 try renderExpression(allocator, ais, tree, if_node.condition, Space.None); // condition
1934
1935 const body_is_if_block = if_node.body.tag == .If;
1936 const body_is_block = nodeIsBlock(if_node.body);
1937
1938 if (body_is_if_block) {
1939 try renderExtraNewline(tree, ais, if_node.body);
1940 } else if (body_is_block) {
1941 const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
1942 try renderToken(tree, ais, rparen, after_rparen_space); // )
1943
1944 if (if_node.payload) |payload| {
1945 try renderExpression(allocator, ais, tree, payload, Space.BlockStart); // |x|
1946 }
1947
1948 if (if_node.@"else") |@"else"| {
1949 try renderExpression(allocator, ais, tree, if_node.body, Space.SpaceOrOutdent);
1950 return renderExpression(allocator, ais, tree, &@"else".base, space);
1951 } else {
1952 return renderExpression(allocator, ais, tree, if_node.body, space);
1953 }
1954 }
1955
1956 const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken());
1957
1958 if (src_has_newline) {
1959 const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space;
1960
1961 {
1962 ais.pushIndent();
1963 defer ais.popIndent();
1964 try renderToken(tree, ais, rparen, after_rparen_space); // )
1965 }
1966
1967 if (if_node.payload) |payload| {
1968 try renderExpression(allocator, ais, tree, payload, Space.Newline);
1969 }
1970
1971 if (if_node.@"else") |@"else"| {
1972 const else_is_block = nodeIsBlock(@"else".body);
1973
1974 {
1975 ais.pushIndent();
1976 defer ais.popIndent();
1977 try renderExpression(allocator, ais, tree, if_node.body, Space.Newline);
1978 }
1979
1980 if (else_is_block) {
1981 try renderToken(tree, ais, @"else".else_token, Space.Space); // else
1982
1983 if (@"else".payload) |payload| {
1984 try renderExpression(allocator, ais, tree, payload, Space.Space);
1985 }
1986
1987 return renderExpression(allocator, ais, tree, @"else".body, space);
1988 } else {
1989 const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;
1990 try renderToken(tree, ais, @"else".else_token, after_else_space); // else
1991
1992 if (@"else".payload) |payload| {
1993 try renderExpression(allocator, ais, tree, payload, Space.Newline);
1994 }
1995
1996 ais.pushIndent();
1997 defer ais.popIndent();
1998 return renderExpression(allocator, ais, tree, @"else".body, space);
1999 }
2000 } else {
2001 ais.pushIndent();
2002 defer ais.popIndent();
2003 return renderExpression(allocator, ais, tree, if_node.body, space);
2004 }
2005 }
2006
2007 // Single line if statement
2008
2009 try renderToken(tree, ais, rparen, Space.Space); // )
2010
2011 if (if_node.payload) |payload| {
2012 try renderExpression(allocator, ais, tree, payload, Space.Space);
2013 }
2014
2015 if (if_node.@"else") |@"else"| {
2016 try renderExpression(allocator, ais, tree, if_node.body, Space.Space);
2017 try renderToken(tree, ais, @"else".else_token, Space.Space);
2018
2019 if (@"else".payload) |payload| {
2020 try renderExpression(allocator, ais, tree, payload, Space.Space);
2021 }
2022
2023 return renderExpression(allocator, ais, tree, @"else".body, space);
2024 } else {
2025 return renderExpression(allocator, ais, tree, if_node.body, space);
2026 }288 }
2027 },289 const nodes_data = tree.nodes.items(.data);
290 const statements = tree.extra_data[nodes_data[node].lhs..nodes_data[node].rhs];
2028291
2029 .Asm => {292 if (statements.len == 0) {
2030 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);293 ais.pushIndentNextLine();
2031294 try renderToken(ais, tree, lbrace, .None);
2032 try renderToken(tree, ais, asm_node.asm_token, Space.Space); // asm295 ais.popIndent();
2033296 const rbrace = lbrace + 1;
2034 if (asm_node.volatile_token) |volatile_token| {297 return renderToken(ais, tree, rbrace, space);
2035 try renderToken(tree, ais, volatile_token, Space.Space); // volatile
2036 try renderToken(tree, ais, tree.nextToken(volatile_token), Space.None); // (
2037 } else {298 } else {
2038 try renderToken(tree, ais, tree.nextToken(asm_node.asm_token), Space.None); // (299 ais.pushIndentNextLine();
2039 }
2040300
2041 asmblk: {301 try renderToken(ais, tree, lbrace, .Newline);
2042 ais.pushIndent();
2043 defer ais.popIndent();
2044302
2045 if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {303 for (statements) |statement, i| {
2046 try renderExpression(allocator, ais, tree, asm_node.template, Space.None);304 try renderStatement(ais, tree, statement);
2047 break :asmblk;
2048 }
2049305
2050 try renderExpression(allocator, ais, tree, asm_node.template, Space.Newline);306 if (i + 1 < statements.len) {
2051307 try renderExtraNewline(tree, ais, statements[i + 1]);
2052 ais.setIndentDelta(asm_indent_delta);
2053 defer ais.setIndentDelta(indent_delta);
2054
2055 const colon1 = tree.nextToken(asm_node.template.lastToken());
2056
2057 const colon2 = if (asm_node.outputs.len == 0) blk: {
2058 try renderToken(tree, ais, colon1, Space.Newline); // :
2059
2060 break :blk tree.nextToken(colon1);
2061 } else blk: {
2062 try renderToken(tree, ais, colon1, Space.Space); // :
2063
2064 ais.pushIndent();
2065 defer ais.popIndent();
2066
2067 for (asm_node.outputs) |*asm_output, i| {
2068 if (i + 1 < asm_node.outputs.len) {
2069 const next_asm_output = asm_node.outputs[i + 1];
2070 try renderAsmOutput(allocator, ais, tree, asm_output, Space.None);
2071
2072 const comma = tree.prevToken(next_asm_output.firstToken());
2073 try renderToken(tree, ais, comma, Space.Newline); // ,
2074 try renderExtraNewlineToken(tree, ais, next_asm_output.firstToken());
2075 } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
2076 try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
2077 break :asmblk;
2078 } else {
2079 try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
2080 const comma_or_colon = tree.nextToken(asm_output.lastToken());
2081 break :blk switch (tree.token_ids[comma_or_colon]) {
2082 .Comma => tree.nextToken(comma_or_colon),
2083 else => comma_or_colon,
2084 };
2085 }
2086 }
2087 unreachable;
2088 };
2089
2090 const colon3 = if (asm_node.inputs.len == 0) blk: {
2091 try renderToken(tree, ais, colon2, Space.Newline); // :
2092 break :blk tree.nextToken(colon2);
2093 } else blk: {
2094 try renderToken(tree, ais, colon2, Space.Space); // :
2095 ais.pushIndent();
2096 defer ais.popIndent();
2097 for (asm_node.inputs) |*asm_input, i| {
2098 if (i + 1 < asm_node.inputs.len) {
2099 const next_asm_input = &asm_node.inputs[i + 1];
2100 try renderAsmInput(allocator, ais, tree, asm_input, Space.None);
2101
2102 const comma = tree.prevToken(next_asm_input.firstToken());
2103 try renderToken(tree, ais, comma, Space.Newline); // ,
2104 try renderExtraNewlineToken(tree, ais, next_asm_input.firstToken());
2105 } else if (asm_node.clobbers.len == 0) {
2106 try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
2107 break :asmblk;
2108 } else {
2109 try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
2110 const comma_or_colon = tree.nextToken(asm_input.lastToken());
2111 break :blk switch (tree.token_ids[comma_or_colon]) {
2112 .Comma => tree.nextToken(comma_or_colon),
2113 else => comma_or_colon,
2114 };
2115 }
2116 }
2117 unreachable;
2118 };
2119
2120 try renderToken(tree, ais, colon3, Space.Space); // :
2121 ais.pushIndent();
2122 defer ais.popIndent();
2123 for (asm_node.clobbers) |clobber_node, i| {
2124 if (i + 1 >= asm_node.clobbers.len) {
2125 try renderExpression(allocator, ais, tree, clobber_node, Space.Newline);
2126 break :asmblk;
2127 } else {
2128 try renderExpression(allocator, ais, tree, clobber_node, Space.None);
2129 const comma = tree.nextToken(clobber_node.lastToken());
2130 try renderToken(tree, ais, comma, Space.Space); // ,
2131 }308 }
2132 }309 }
310 ais.popIndent();
311 const rbrace = tree.lastToken(statements[statements.len - 1]) + 1;
312 return renderToken(ais, tree, rbrace, space);
2133 }313 }
2134
2135 return renderToken(tree, ais, asm_node.rparen, space);
2136 },314 },
2137315
2138 .EnumLiteral => {316 //.Defer => {
2139 const enum_literal = @fieldParentPtr(ast.Node.EnumLiteral, "base", base);317 // const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
2140318
2141 try renderToken(tree, ais, enum_literal.dot, Space.None); // .319 // try renderToken(ais, tree, defer_node.defer_token, Space.Space);
2142 return renderToken(tree, ais, enum_literal.name, space); // name320 // if (defer_node.payload) |payload| {
321 // try renderExpression(allocator, ais, tree, payload, Space.Space);
322 // }
323 // return renderExpression(allocator, ais, tree, defer_node.expr, space);
324 //},
325 .Comptime => {
326 const comptime_token = tree.nodes.items(.main_token)[node];
327 const block = tree.nodes.items(.data)[node].lhs;
328 try renderToken(ais, tree, comptime_token, .Space);
329 return renderExpression(ais, tree, block, space);
2143 },330 },
2144331 //.Nosuspend => {
2145 .ContainerField,332 // const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base);
2146 .Root,333 // if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) {
2147 .VarDecl,334 // // TODO: remove this
2148 .Use,335 // try ais.writer().writeAll("nosuspend ");
2149 .TestDecl,336 // } else {
2150 => unreachable,337 // try renderToken(ais, tree, nosuspend_node.nosuspend_token, Space.Space);
338 // }
339 // return renderExpression(allocator, ais, tree, nosuspend_node.expr, space);
340 //},
341
342 //.Suspend => {
343 // const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
344
345 // if (suspend_node.body) |body| {
346 // try renderToken(ais, tree, suspend_node.suspend_token, Space.Space);
347 // return renderExpression(allocator, ais, tree, body, space);
348 // } else {
349 // return renderToken(ais, tree, suspend_node.suspend_token, space);
350 // }
351 //},
352
353 //.Catch => {
354 // const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base);
355
356 // const op_space = Space.Space;
357 // try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
358
359 // const after_op_space = blk: {
360 // const same_line = tree.tokensOnSameLine(infix_op_node.op_token, tree.nextToken(infix_op_node.op_token));
361 // break :blk if (same_line) op_space else Space.Newline;
362 // };
363
364 // try renderToken(ais, tree, infix_op_node.op_token, after_op_space);
365
366 // if (infix_op_node.payload) |payload| {
367 // try renderExpression(allocator, ais, tree, payload, Space.Space);
368 // }
369
370 // ais.pushIndentOneShot();
371 // return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
372 //},
373
374 //.Add,
375 //.AddWrap,
376 //.ArrayCat,
377 //.ArrayMult,
378 //.Assign,
379 //.AssignBitAnd,
380 //.AssignBitOr,
381 //.AssignBitShiftLeft,
382 //.AssignBitShiftRight,
383 //.AssignBitXor,
384 //.AssignDiv,
385 //.AssignSub,
386 //.AssignSubWrap,
387 //.AssignMod,
388 //.AssignAdd,
389 //.AssignAddWrap,
390 //.AssignMul,
391 //.AssignMulWrap,
392 //.BangEqual,
393 //.BitAnd,
394 //.BitOr,
395 //.BitShiftLeft,
396 //.BitShiftRight,
397 //.BitXor,
398 //.BoolAnd,
399 //.BoolOr,
400 //.Div,
401 //.EqualEqual,
402 //.ErrorUnion,
403 //.GreaterOrEqual,
404 //.GreaterThan,
405 //.LessOrEqual,
406 //.LessThan,
407 //.MergeErrorSets,
408 //.Mod,
409 //.Mul,
410 //.MulWrap,
411 //.Period,
412 //.Range,
413 //.Sub,
414 //.SubWrap,
415 //.OrElse,
416 //=> {
417 // const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base);
418
419 // const op_space = switch (base.tag) {
420 // .Period, .ErrorUnion, .Range => Space.None,
421 // else => Space.Space,
422 // };
423 // try renderExpression(allocator, ais, tree, infix_op_node.lhs, op_space);
424
425 // const after_op_space = blk: {
426 // const loc = tree.tokenLocation(tree.token_locs[infix_op_node.op_token].end, tree.nextToken(infix_op_node.op_token));
427 // break :blk if (loc.line == 0) op_space else Space.Newline;
428 // };
429
430 // {
431 // ais.pushIndent();
432 // defer ais.popIndent();
433 // try renderToken(ais, tree, infix_op_node.op_token, after_op_space);
434 // }
435 // ais.pushIndentOneShot();
436 // return renderExpression(allocator, ais, tree, infix_op_node.rhs, space);
437 //},
438
439 //.BitNot,
440 //.BoolNot,
441 //.Negation,
442 //.NegationWrap,
443 //.OptionalType,
444 //.AddressOf,
445 //=> {
446 // const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
447 // try renderToken(ais, tree, casted_node.op_token, Space.None);
448 // return renderExpression(allocator, ais, tree, casted_node.rhs, space);
449 //},
450
451 //.Try,
452 //.Resume,
453 //.Await,
454 //=> {
455 // const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
456 // try renderToken(ais, tree, casted_node.op_token, Space.Space);
457 // return renderExpression(allocator, ais, tree, casted_node.rhs, space);
458 //},
459
460 //.ArrayType => {
461 // const array_type = @fieldParentPtr(ast.Node.ArrayType, "base", base);
462 // return renderArrayType(
463 // allocator,
464 // ais,
465 // tree,
466 // array_type.op_token,
467 // array_type.rhs,
468 // array_type.len_expr,
469 // null,
470 // space,
471 // );
472 //},
473 //.ArrayTypeSentinel => {
474 // const array_type = @fieldParentPtr(ast.Node.ArrayTypeSentinel, "base", base);
475 // return renderArrayType(
476 // allocator,
477 // ais,
478 // tree,
479 // array_type.op_token,
480 // array_type.rhs,
481 // array_type.len_expr,
482 // array_type.sentinel,
483 // space,
484 // );
485 //},
486
487 //.PtrType => {
488 // const ptr_type = @fieldParentPtr(ast.Node.PtrType, "base", base);
489 // const op_tok_id = tree.token_tags[ptr_type.op_token];
490 // switch (op_tok_id) {
491 // .Asterisk, .AsteriskAsterisk => try ais.writer().writeByte('*'),
492 // .LBracket => if (tree.token_tags[ptr_type.op_token + 2] == .Identifier)
493 // try ais.writer().writeAll("[*c")
494 // else
495 // try ais.writer().writeAll("[*"),
496 // else => unreachable,
497 // }
498 // if (ptr_type.ptr_info.sentinel) |sentinel| {
499 // const colon_token = tree.prevToken(sentinel.firstToken());
500 // try renderToken(ais, tree, colon_token, Space.None); // :
501 // const sentinel_space = switch (op_tok_id) {
502 // .LBracket => Space.None,
503 // else => Space.Space,
504 // };
505 // try renderExpression(allocator, ais, tree, sentinel, sentinel_space);
506 // }
507 // switch (op_tok_id) {
508 // .Asterisk, .AsteriskAsterisk => {},
509 // .LBracket => try ais.writer().writeByte(']'),
510 // else => unreachable,
511 // }
512 // if (ptr_type.ptr_info.allowzero_token) |allowzero_token| {
513 // try renderToken(ais, tree, allowzero_token, Space.Space); // allowzero
514 // }
515 // if (ptr_type.ptr_info.align_info) |align_info| {
516 // const lparen_token = tree.prevToken(align_info.node.firstToken());
517 // const align_token = tree.prevToken(lparen_token);
518
519 // try renderToken(ais, tree, align_token, Space.None); // align
520 // try renderToken(ais, tree, lparen_token, Space.None); // (
521
522 // try renderExpression(allocator, ais, tree, align_info.node, Space.None);
523
524 // if (align_info.bit_range) |bit_range| {
525 // const colon1 = tree.prevToken(bit_range.start.firstToken());
526 // const colon2 = tree.prevToken(bit_range.end.firstToken());
527
528 // try renderToken(ais, tree, colon1, Space.None); // :
529 // try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
530 // try renderToken(ais, tree, colon2, Space.None); // :
531 // try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
532
533 // const rparen_token = tree.nextToken(bit_range.end.lastToken());
534 // try renderToken(ais, tree, rparen_token, Space.Space); // )
535 // } else {
536 // const rparen_token = tree.nextToken(align_info.node.lastToken());
537 // try renderToken(ais, tree, rparen_token, Space.Space); // )
538 // }
539 // }
540 // if (ptr_type.ptr_info.const_token) |const_token| {
541 // try renderToken(ais, tree, const_token, Space.Space); // const
542 // }
543 // if (ptr_type.ptr_info.volatile_token) |volatile_token| {
544 // try renderToken(ais, tree, volatile_token, Space.Space); // volatile
545 // }
546 // return renderExpression(allocator, ais, tree, ptr_type.rhs, space);
547 //},
548
549 //.SliceType => {
550 // const slice_type = @fieldParentPtr(ast.Node.SliceType, "base", base);
551 // try renderToken(ais, tree, slice_type.op_token, Space.None); // [
552 // if (slice_type.ptr_info.sentinel) |sentinel| {
553 // const colon_token = tree.prevToken(sentinel.firstToken());
554 // try renderToken(ais, tree, colon_token, Space.None); // :
555 // try renderExpression(allocator, ais, tree, sentinel, Space.None);
556 // try renderToken(ais, tree, tree.nextToken(sentinel.lastToken()), Space.None); // ]
557 // } else {
558 // try renderToken(ais, tree, tree.nextToken(slice_type.op_token), Space.None); // ]
559 // }
560
561 // if (slice_type.ptr_info.allowzero_token) |allowzero_token| {
562 // try renderToken(ais, tree, allowzero_token, Space.Space); // allowzero
563 // }
564 // if (slice_type.ptr_info.align_info) |align_info| {
565 // const lparen_token = tree.prevToken(align_info.node.firstToken());
566 // const align_token = tree.prevToken(lparen_token);
567
568 // try renderToken(ais, tree, align_token, Space.None); // align
569 // try renderToken(ais, tree, lparen_token, Space.None); // (
570
571 // try renderExpression(allocator, ais, tree, align_info.node, Space.None);
572
573 // if (align_info.bit_range) |bit_range| {
574 // const colon1 = tree.prevToken(bit_range.start.firstToken());
575 // const colon2 = tree.prevToken(bit_range.end.firstToken());
576
577 // try renderToken(ais, tree, colon1, Space.None); // :
578 // try renderExpression(allocator, ais, tree, bit_range.start, Space.None);
579 // try renderToken(ais, tree, colon2, Space.None); // :
580 // try renderExpression(allocator, ais, tree, bit_range.end, Space.None);
581
582 // const rparen_token = tree.nextToken(bit_range.end.lastToken());
583 // try renderToken(ais, tree, rparen_token, Space.Space); // )
584 // } else {
585 // const rparen_token = tree.nextToken(align_info.node.lastToken());
586 // try renderToken(ais, tree, rparen_token, Space.Space); // )
587 // }
588 // }
589 // if (slice_type.ptr_info.const_token) |const_token| {
590 // try renderToken(ais, tree, const_token, Space.Space);
591 // }
592 // if (slice_type.ptr_info.volatile_token) |volatile_token| {
593 // try renderToken(ais, tree, volatile_token, Space.Space);
594 // }
595 // return renderExpression(allocator, ais, tree, slice_type.rhs, space);
596 //},
597
598 //.ArrayInitializer, .ArrayInitializerDot => {
599 // var rtoken: ast.TokenIndex = undefined;
600 // var exprs: []ast.Node.Index = undefined;
601 // const lhs: union(enum) { dot: ast.TokenIndex, node: ast.Node.Index } = switch (base.tag) {
602 // .ArrayInitializerDot => blk: {
603 // const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base);
604 // rtoken = casted.rtoken;
605 // exprs = casted.list();
606 // break :blk .{ .dot = casted.dot };
607 // },
608 // .ArrayInitializer => blk: {
609 // const casted = @fieldParentPtr(ast.Node.ArrayInitializer, "base", base);
610 // rtoken = casted.rtoken;
611 // exprs = casted.list();
612 // break :blk .{ .node = casted.lhs };
613 // },
614 // else => unreachable,
615 // };
616
617 // const lbrace = switch (lhs) {
618 // .dot => |dot| tree.nextToken(dot),
619 // .node => |node| tree.nextToken(node.lastToken()),
620 // };
621
622 // switch (lhs) {
623 // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
624 // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
625 // }
626
627 // if (exprs.len == 0) {
628 // try renderToken(ais, tree, lbrace, Space.None);
629 // return renderToken(ais, tree, rtoken, space);
630 // }
631
632 // if (exprs.len == 1 and exprs[0].tag != .MultilineStringLiteral and tree.token_tags[exprs[0].*.lastToken() + 1] == .RBrace) {
633 // const expr = exprs[0];
634
635 // try renderToken(ais, tree, lbrace, Space.None);
636 // try renderExpression(allocator, ais, tree, expr, Space.None);
637 // return renderToken(ais, tree, rtoken, space);
638 // }
639
640 // // scan to find row size
641 // if (rowSize(tree, exprs, rtoken) != null) {
642 // {
643 // ais.pushIndentNextLine();
644 // defer ais.popIndent();
645 // try renderToken(ais, tree, lbrace, Space.Newline);
646
647 // var expr_index: usize = 0;
648 // while (rowSize(tree, exprs[expr_index..], rtoken)) |row_size| {
649 // const row_exprs = exprs[expr_index..];
650 // // A place to store the width of each expression and its column's maximum
651 // var widths = try allocator.alloc(usize, row_exprs.len + row_size);
652 // defer allocator.free(widths);
653 // mem.set(usize, widths, 0);
654
655 // var expr_newlines = try allocator.alloc(bool, row_exprs.len);
656 // defer allocator.free(expr_newlines);
657 // mem.set(bool, expr_newlines, false);
658
659 // var expr_widths = widths[0 .. widths.len - row_size];
660 // var column_widths = widths[widths.len - row_size ..];
661
662 // // Find next row with trailing comment (if any) to end the current section
663 // var section_end = sec_end: {
664 // var this_line_first_expr: usize = 0;
665 // var this_line_size = rowSize(tree, row_exprs, rtoken);
666 // for (row_exprs) |expr, i| {
667 // // Ignore comment on first line of this section
668 // if (i == 0 or tree.tokensOnSameLine(row_exprs[0].firstToken(), expr.lastToken())) continue;
669 // // Track start of line containing comment
670 // if (!tree.tokensOnSameLine(row_exprs[this_line_first_expr].firstToken(), expr.lastToken())) {
671 // this_line_first_expr = i;
672 // this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rtoken);
673 // }
674
675 // const maybe_comma = expr.lastToken() + 1;
676 // const maybe_comment = expr.lastToken() + 2;
677 // if (maybe_comment < tree.token_tags.len) {
678 // if (tree.token_tags[maybe_comma] == .Comma and
679 // tree.token_tags[maybe_comment] == .LineComment and
680 // tree.tokensOnSameLine(expr.lastToken(), maybe_comment))
681 // {
682 // var comment_token_loc = tree.token_locs[maybe_comment];
683 // const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2;
684 // if (!comment_is_empty) {
685 // // Found row ending in comment
686 // break :sec_end i - this_line_size.? + 1;
687 // }
688 // }
689 // }
690 // }
691 // break :sec_end row_exprs.len;
692 // };
693 // expr_index += section_end;
694
695 // const section_exprs = row_exprs[0..section_end];
696
697 // // Null stream for counting the printed length of each expression
698 // var line_find_stream = std.io.findByteWriter('\n', std.io.null_writer);
699 // var counting_stream = std.io.countingWriter(line_find_stream.writer());
700 // var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer());
701
702 // // Calculate size of columns in current section
703 // var column_counter: usize = 0;
704 // var single_line = true;
705 // for (section_exprs) |expr, i| {
706 // if (i + 1 < section_exprs.len) {
707 // counting_stream.bytes_written = 0;
708 // line_find_stream.byte_found = false;
709 // try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
710 // const width = @intCast(usize, counting_stream.bytes_written);
711 // expr_widths[i] = width;
712 // expr_newlines[i] = line_find_stream.byte_found;
713
714 // if (!line_find_stream.byte_found) {
715 // const column = column_counter % row_size;
716 // column_widths[column] = std.math.max(column_widths[column], width);
717
718 // const expr_last_token = expr.*.lastToken() + 1;
719 // const next_expr = section_exprs[i + 1];
720 // const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, next_expr.*.firstToken());
721
722 // column_counter += 1;
723
724 // if (loc.line != 0) single_line = false;
725 // } else {
726 // single_line = false;
727 // column_counter = 0;
728 // }
729 // } else {
730 // counting_stream.bytes_written = 0;
731 // try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None);
732 // const width = @intCast(usize, counting_stream.bytes_written);
733 // expr_widths[i] = width;
734 // expr_newlines[i] = line_find_stream.byte_found;
735
736 // if (!line_find_stream.byte_found) {
737 // const column = column_counter % row_size;
738 // column_widths[column] = std.math.max(column_widths[column], width);
739 // }
740 // break;
741 // }
742 // }
743
744 // // Render exprs in current section
745 // column_counter = 0;
746 // var last_col_index: usize = row_size - 1;
747 // for (section_exprs) |expr, i| {
748 // if (i + 1 < section_exprs.len) {
749 // const next_expr = section_exprs[i + 1];
750 // try renderExpression(allocator, ais, tree, expr, Space.None);
751
752 // const comma = tree.nextToken(expr.*.lastToken());
753
754 // if (column_counter != last_col_index) {
755 // if (!expr_newlines[i] and !expr_newlines[i + 1]) {
756 // // Neither the current or next expression is multiline
757 // try renderToken(ais, tree, comma, Space.Space); // ,
758 // assert(column_widths[column_counter % row_size] >= expr_widths[i]);
759 // const padding = column_widths[column_counter % row_size] - expr_widths[i];
760 // try ais.writer().writeByteNTimes(' ', padding);
761
762 // column_counter += 1;
763 // continue;
764 // }
765 // }
766 // if (single_line and row_size != 1) {
767 // try renderToken(ais, tree, comma, Space.Space); // ,
768 // continue;
769 // }
770
771 // column_counter = 0;
772 // try renderToken(ais, tree, comma, Space.Newline); // ,
773 // try renderExtraNewline(tree, ais, next_expr);
774 // } else {
775 // const maybe_comma = tree.nextToken(expr.*.lastToken());
776 // if (tree.token_tags[maybe_comma] == .Comma) {
777 // try renderExpression(allocator, ais, tree, expr, Space.None); // ,
778 // try renderToken(ais, tree, maybe_comma, Space.Newline); // ,
779 // } else {
780 // try renderExpression(allocator, ais, tree, expr, Space.Comma); // ,
781 // }
782 // }
783 // }
784
785 // if (expr_index == exprs.len) {
786 // break;
787 // }
788 // }
789 // }
790
791 // return renderToken(ais, tree, rtoken, space);
792 // }
793
794 // // Single line
795 // try renderToken(ais, tree, lbrace, Space.Space);
796 // for (exprs) |expr, i| {
797 // if (i + 1 < exprs.len) {
798 // const next_expr = exprs[i + 1];
799 // try renderExpression(allocator, ais, tree, expr, Space.None);
800 // const comma = tree.nextToken(expr.*.lastToken());
801 // try renderToken(ais, tree, comma, Space.Space); // ,
802 // } else {
803 // try renderExpression(allocator, ais, tree, expr, Space.Space);
804 // }
805 // }
806
807 // return renderToken(ais, tree, rtoken, space);
808 //},
809
810 //.StructInitializer, .StructInitializerDot => {
811 // var rtoken: ast.TokenIndex = undefined;
812 // var field_inits: []ast.Node.Index = undefined;
813 // const lhs: union(enum) { dot: ast.TokenIndex, node: ast.Node.Index } = switch (base.tag) {
814 // .StructInitializerDot => blk: {
815 // const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base);
816 // rtoken = casted.rtoken;
817 // field_inits = casted.list();
818 // break :blk .{ .dot = casted.dot };
819 // },
820 // .StructInitializer => blk: {
821 // const casted = @fieldParentPtr(ast.Node.StructInitializer, "base", base);
822 // rtoken = casted.rtoken;
823 // field_inits = casted.list();
824 // break :blk .{ .node = casted.lhs };
825 // },
826 // else => unreachable,
827 // };
828
829 // const lbrace = switch (lhs) {
830 // .dot => |dot| tree.nextToken(dot),
831 // .node => |node| tree.nextToken(node.lastToken()),
832 // };
833
834 // if (field_inits.len == 0) {
835 // switch (lhs) {
836 // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
837 // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
838 // }
839
840 // {
841 // ais.pushIndentNextLine();
842 // defer ais.popIndent();
843 // try renderToken(ais, tree, lbrace, Space.None);
844 // }
845
846 // return renderToken(ais, tree, rtoken, space);
847 // }
848
849 // const src_has_trailing_comma = blk: {
850 // const maybe_comma = tree.prevToken(rtoken);
851 // break :blk tree.token_tags[maybe_comma] == .Comma;
852 // };
853
854 // const src_same_line = blk: {
855 // const loc = tree.tokenLocation(tree.token_locs[lbrace].end, rtoken);
856 // break :blk loc.line == 0;
857 // };
858
859 // const expr_outputs_one_line = blk: {
860 // // render field expressions until a LF is found
861 // for (field_inits) |field_init| {
862 // var find_stream = std.io.findByteWriter('\n', std.io.null_writer);
863 // var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, find_stream.writer());
864
865 // try renderExpression(allocator, &auto_indenting_stream, tree, field_init, Space.None);
866 // if (find_stream.byte_found) break :blk false;
867 // }
868 // break :blk true;
869 // };
870
871 // if (field_inits.len == 1) blk: {
872 // if (field_inits[0].cast(ast.Node.FieldInitializer)) |field_init| {
873 // switch (field_init.expr.tag) {
874 // .StructInitializer,
875 // .StructInitializerDot,
876 // => break :blk,
877 // else => {},
878 // }
879 // }
880
881 // // if the expression outputs to multiline, make this struct multiline
882 // if (!expr_outputs_one_line or src_has_trailing_comma) {
883 // break :blk;
884 // }
885
886 // switch (lhs) {
887 // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
888 // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
889 // }
890 // try renderToken(ais, tree, lbrace, Space.Space);
891 // try renderExpression(allocator, ais, tree, field_inits[0], Space.Space);
892 // return renderToken(ais, tree, rtoken, space);
893 // }
894
895 // if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
896 // // render all on one line, no trailing comma
897 // switch (lhs) {
898 // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
899 // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
900 // }
901 // try renderToken(ais, tree, lbrace, Space.Space);
902
903 // for (field_inits) |field_init, i| {
904 // if (i + 1 < field_inits.len) {
905 // try renderExpression(allocator, ais, tree, field_init, Space.None);
906
907 // const comma = tree.nextToken(field_init.lastToken());
908 // try renderToken(ais, tree, comma, Space.Space);
909 // } else {
910 // try renderExpression(allocator, ais, tree, field_init, Space.Space);
911 // }
912 // }
913
914 // return renderToken(ais, tree, rtoken, space);
915 // }
916
917 // {
918 // switch (lhs) {
919 // .dot => |dot| try renderToken(ais, tree, dot, Space.None),
920 // .node => |node| try renderExpression(allocator, ais, tree, node, Space.None),
921 // }
922
923 // ais.pushIndentNextLine();
924 // defer ais.popIndent();
925
926 // try renderToken(ais, tree, lbrace, Space.Newline);
927
928 // for (field_inits) |field_init, i| {
929 // if (i + 1 < field_inits.len) {
930 // const next_field_init = field_inits[i + 1];
931 // try renderExpression(allocator, ais, tree, field_init, Space.None);
932
933 // const comma = tree.nextToken(field_init.lastToken());
934 // try renderToken(ais, tree, comma, Space.Newline);
935
936 // try renderExtraNewline(tree, ais, next_field_init);
937 // } else {
938 // try renderExpression(allocator, ais, tree, field_init, Space.Comma);
939 // }
940 // }
941 // }
942
943 // return renderToken(ais, tree, rtoken, space);
944 //},
945
946 //.Call => {
947 // const call = @fieldParentPtr(ast.Node.Call, "base", base);
948 // if (call.async_token) |async_token| {
949 // try renderToken(ais, tree, async_token, Space.Space);
950 // }
951
952 // try renderExpression(allocator, ais, tree, call.lhs, Space.None);
953
954 // const lparen = tree.nextToken(call.lhs.lastToken());
955
956 // if (call.params_len == 0) {
957 // try renderToken(ais, tree, lparen, Space.None);
958 // return renderToken(ais, tree, call.rtoken, space);
959 // }
960
961 // const src_has_trailing_comma = blk: {
962 // const maybe_comma = tree.prevToken(call.rtoken);
963 // break :blk tree.token_tags[maybe_comma] == .Comma;
964 // };
965
966 // if (src_has_trailing_comma) {
967 // {
968 // ais.pushIndent();
969 // defer ais.popIndent();
970
971 // try renderToken(ais, tree, lparen, Space.Newline); // (
972 // const params = call.params();
973 // for (params) |param_node, i| {
974 // if (i + 1 < params.len) {
975 // const next_node = params[i + 1];
976 // try renderExpression(allocator, ais, tree, param_node, Space.None);
977
978 // // Unindent the comma for multiline string literals
979 // const maybe_multiline_string = param_node.firstToken();
980 // const is_multiline_string = tree.token_tags[maybe_multiline_string] == .MultilineStringLiteralLine;
981 // if (is_multiline_string) ais.popIndent();
982 // defer if (is_multiline_string) ais.pushIndent();
983
984 // const comma = tree.nextToken(param_node.lastToken());
985 // try renderToken(ais, tree, comma, Space.Newline); // ,
986 // try renderExtraNewline(tree, ais, next_node);
987 // } else {
988 // try renderExpression(allocator, ais, tree, param_node, Space.Comma);
989 // }
990 // }
991 // }
992 // return renderToken(ais, tree, call.rtoken, space);
993 // }
994
995 // try renderToken(ais, tree, lparen, Space.None); // (
996
997 // const params = call.params();
998 // for (params) |param_node, i| {
999 // const maybe_comment = param_node.firstToken() - 1;
1000 // const maybe_multiline_string = param_node.firstToken();
1001 // if (tree.token_tags[maybe_multiline_string] == .MultilineStringLiteralLine or tree.token_tags[maybe_comment] == .LineComment) {
1002 // ais.pushIndentOneShot();
1003 // }
1004
1005 // try renderExpression(allocator, ais, tree, param_node, Space.None);
1006
1007 // if (i + 1 < params.len) {
1008 // const comma = tree.nextToken(param_node.lastToken());
1009 // try renderToken(ais, tree, comma, Space.Space);
1010 // }
1011 // }
1012 // return renderToken(ais, tree, call.rtoken, space); // )
1013 //},
1014
1015 //.ArrayAccess => {
1016 // const suffix_op = base.castTag(.ArrayAccess).?;
1017
1018 // const lbracket = tree.nextToken(suffix_op.lhs.lastToken());
1019 // const rbracket = tree.nextToken(suffix_op.index_expr.lastToken());
1020
1021 // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1022 // try renderToken(ais, tree, lbracket, Space.None); // [
1023
1024 // const starts_with_comment = tree.token_tags[lbracket + 1] == .LineComment;
1025 // const ends_with_comment = tree.token_tags[rbracket - 1] == .LineComment;
1026 // {
1027 // const new_space = if (ends_with_comment) Space.Newline else Space.None;
1028
1029 // ais.pushIndent();
1030 // defer ais.popIndent();
1031 // try renderExpression(allocator, ais, tree, suffix_op.index_expr, new_space);
1032 // }
1033 // if (starts_with_comment) try ais.maybeInsertNewline();
1034 // return renderToken(ais, tree, rbracket, space); // ]
1035 //},
1036
1037 //.Slice => {
1038 // const suffix_op = base.castTag(.Slice).?;
1039 // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1040
1041 // const lbracket = tree.prevToken(suffix_op.start.firstToken());
1042 // const dotdot = tree.nextToken(suffix_op.start.lastToken());
1043
1044 // const after_start_space_bool = nodeCausesSliceOpSpace(suffix_op.start) or
1045 // (if (suffix_op.end) |end| nodeCausesSliceOpSpace(end) else false);
1046 // const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
1047 // const after_op_space = if (suffix_op.end != null) after_start_space else Space.None;
1048
1049 // try renderToken(ais, tree, lbracket, Space.None); // [
1050 // try renderExpression(allocator, ais, tree, suffix_op.start, after_start_space);
1051 // try renderToken(ais, tree, dotdot, after_op_space); // ..
1052 // if (suffix_op.end) |end| {
1053 // const after_end_space = if (suffix_op.sentinel != null) Space.Space else Space.None;
1054 // try renderExpression(allocator, ais, tree, end, after_end_space);
1055 // }
1056 // if (suffix_op.sentinel) |sentinel| {
1057 // const colon = tree.prevToken(sentinel.firstToken());
1058 // try renderToken(ais, tree, colon, Space.None); // :
1059 // try renderExpression(allocator, ais, tree, sentinel, Space.None);
1060 // }
1061 // return renderToken(ais, tree, suffix_op.rtoken, space); // ]
1062 //},
1063
1064 //.Deref => {
1065 // const suffix_op = base.castTag(.Deref).?;
1066
1067 // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1068 // return renderToken(ais, tree, suffix_op.rtoken, space); // .*
1069 //},
1070 //.UnwrapOptional => {
1071 // const suffix_op = base.castTag(.UnwrapOptional).?;
1072
1073 // try renderExpression(allocator, ais, tree, suffix_op.lhs, Space.None);
1074 // try renderToken(ais, tree, tree.prevToken(suffix_op.rtoken), Space.None); // .
1075 // return renderToken(ais, tree, suffix_op.rtoken, space); // ?
1076 //},
1077
1078 //.Break => {
1079 // const flow_expr = base.castTag(.Break).?;
1080 // const maybe_rhs = flow_expr.getRHS();
1081 // const maybe_label = flow_expr.getLabel();
1082
1083 // if (maybe_label == null and maybe_rhs == null) {
1084 // return renderToken(ais, tree, flow_expr.ltoken, space); // break
1085 // }
1086
1087 // try renderToken(ais, tree, flow_expr.ltoken, Space.Space); // break
1088 // if (maybe_label) |label| {
1089 // const colon = tree.nextToken(flow_expr.ltoken);
1090 // try renderToken(ais, tree, colon, Space.None); // :
1091
1092 // if (maybe_rhs == null) {
1093 // return renderToken(ais, tree, label, space); // label
1094 // }
1095 // try renderToken(ais, tree, label, Space.Space); // label
1096 // }
1097 // return renderExpression(allocator, ais, tree, maybe_rhs.?, space);
1098 //},
1099
1100 //.Continue => {
1101 // const flow_expr = base.castTag(.Continue).?;
1102 // if (flow_expr.getLabel()) |label| {
1103 // try renderToken(ais, tree, flow_expr.ltoken, Space.Space); // continue
1104 // const colon = tree.nextToken(flow_expr.ltoken);
1105 // try renderToken(ais, tree, colon, Space.None); // :
1106 // return renderToken(ais, tree, label, space); // label
1107 // } else {
1108 // return renderToken(ais, tree, flow_expr.ltoken, space); // continue
1109 // }
1110 //},
1111
1112 //.Return => {
1113 // const flow_expr = base.castTag(.Return).?;
1114 // if (flow_expr.getRHS()) |rhs| {
1115 // try renderToken(ais, tree, flow_expr.ltoken, Space.Space);
1116 // return renderExpression(allocator, ais, tree, rhs, space);
1117 // } else {
1118 // return renderToken(ais, tree, flow_expr.ltoken, space);
1119 // }
1120 //},
1121
1122 //.Payload => {
1123 // const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
1124
1125 // try renderToken(ais, tree, payload.lpipe, Space.None);
1126 // try renderExpression(allocator, ais, tree, payload.error_symbol, Space.None);
1127 // return renderToken(ais, tree, payload.rpipe, space);
1128 //},
1129
1130 //.PointerPayload => {
1131 // const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
1132
1133 // try renderToken(ais, tree, payload.lpipe, Space.None);
1134 // if (payload.ptr_token) |ptr_token| {
1135 // try renderToken(ais, tree, ptr_token, Space.None);
1136 // }
1137 // try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
1138 // return renderToken(ais, tree, payload.rpipe, space);
1139 //},
1140
1141 //.PointerIndexPayload => {
1142 // const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
1143
1144 // try renderToken(ais, tree, payload.lpipe, Space.None);
1145 // if (payload.ptr_token) |ptr_token| {
1146 // try renderToken(ais, tree, ptr_token, Space.None);
1147 // }
1148 // try renderExpression(allocator, ais, tree, payload.value_symbol, Space.None);
1149
1150 // if (payload.index_symbol) |index_symbol| {
1151 // const comma = tree.nextToken(payload.value_symbol.lastToken());
1152
1153 // try renderToken(ais, tree, comma, Space.Space);
1154 // try renderExpression(allocator, ais, tree, index_symbol, Space.None);
1155 // }
1156
1157 // return renderToken(ais, tree, payload.rpipe, space);
1158 //},
1159
1160 //.GroupedExpression => {
1161 // const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
1162
1163 // try renderToken(ais, tree, grouped_expr.lparen, Space.None);
1164 // {
1165 // ais.pushIndentOneShot();
1166 // try renderExpression(allocator, ais, tree, grouped_expr.expr, Space.None);
1167 // }
1168 // return renderToken(ais, tree, grouped_expr.rparen, space);
1169 //},
1170
1171 //.FieldInitializer => {
1172 // const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
1173
1174 // try renderToken(ais, tree, field_init.period_token, Space.None); // .
1175 // try renderToken(ais, tree, field_init.name_token, Space.Space); // name
1176 // try renderToken(ais, tree, tree.nextToken(field_init.name_token), Space.Space); // =
1177 // return renderExpression(allocator, ais, tree, field_init.expr, space);
1178 //},
1179
1180 //.ContainerDecl => {
1181 // const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
1182
1183 // if (container_decl.layout_token) |layout_token| {
1184 // try renderToken(ais, tree, layout_token, Space.Space);
1185 // }
1186
1187 // switch (container_decl.init_arg_expr) {
1188 // .None => {
1189 // try renderToken(ais, tree, container_decl.kind_token, Space.Space); // union
1190 // },
1191 // .Enum => |enum_tag_type| {
1192 // try renderToken(ais, tree, container_decl.kind_token, Space.None); // union
1193
1194 // const lparen = tree.nextToken(container_decl.kind_token);
1195 // const enum_token = tree.nextToken(lparen);
1196
1197 // try renderToken(ais, tree, lparen, Space.None); // (
1198 // try renderToken(ais, tree, enum_token, Space.None); // enum
1199
1200 // if (enum_tag_type) |expr| {
1201 // try renderToken(ais, tree, tree.nextToken(enum_token), Space.None); // (
1202 // try renderExpression(allocator, ais, tree, expr, Space.None);
1203
1204 // const rparen = tree.nextToken(expr.lastToken());
1205 // try renderToken(ais, tree, rparen, Space.None); // )
1206 // try renderToken(ais, tree, tree.nextToken(rparen), Space.Space); // )
1207 // } else {
1208 // try renderToken(ais, tree, tree.nextToken(enum_token), Space.Space); // )
1209 // }
1210 // },
1211 // .Type => |type_expr| {
1212 // try renderToken(ais, tree, container_decl.kind_token, Space.None); // union
1213
1214 // const lparen = tree.nextToken(container_decl.kind_token);
1215 // const rparen = tree.nextToken(type_expr.lastToken());
1216
1217 // try renderToken(ais, tree, lparen, Space.None); // (
1218 // try renderExpression(allocator, ais, tree, type_expr, Space.None);
1219 // try renderToken(ais, tree, rparen, Space.Space); // )
1220 // },
1221 // }
1222
1223 // if (container_decl.fields_and_decls_len == 0) {
1224 // {
1225 // ais.pushIndentNextLine();
1226 // defer ais.popIndent();
1227 // try renderToken(ais, tree, container_decl.lbrace_token, Space.None); // {
1228 // }
1229 // return renderToken(ais, tree, container_decl.rbrace_token, space); // }
1230 // }
1231
1232 // const src_has_trailing_comma = blk: {
1233 // var maybe_comma = tree.prevToken(container_decl.lastToken());
1234 // // Doc comments for a field may also appear after the comma, eg.
1235 // // field_name: T, // comment attached to field_name
1236 // if (tree.token_tags[maybe_comma] == .DocComment)
1237 // maybe_comma = tree.prevToken(maybe_comma);
1238 // break :blk tree.token_tags[maybe_comma] == .Comma;
1239 // };
1240
1241 // const fields_and_decls = container_decl.fieldsAndDecls();
1242
1243 // // Check if the first declaration and the { are on the same line
1244 // const src_has_newline = !tree.tokensOnSameLine(
1245 // container_decl.lbrace_token,
1246 // fields_and_decls[0].firstToken(),
1247 // );
1248
1249 // // We can only print all the elements in-line if all the
1250 // // declarations inside are fields
1251 // const src_has_only_fields = blk: {
1252 // for (fields_and_decls) |decl| {
1253 // if (decl.tag != .ContainerField) break :blk false;
1254 // }
1255 // break :blk true;
1256 // };
1257
1258 // if (src_has_trailing_comma or !src_has_only_fields) {
1259 // // One declaration per line
1260 // ais.pushIndentNextLine();
1261 // defer ais.popIndent();
1262 // try renderToken(ais, tree, container_decl.lbrace_token, .Newline); // {
1263
1264 // for (fields_and_decls) |decl, i| {
1265 // try renderContainerDecl(allocator, ais, tree, decl, .Newline);
1266
1267 // if (i + 1 < fields_and_decls.len) {
1268 // try renderExtraNewline(tree, ais, fields_and_decls[i + 1]);
1269 // }
1270 // }
1271 // } else if (src_has_newline) {
1272 // // All the declarations on the same line, but place the items on
1273 // // their own line
1274 // try renderToken(ais, tree, container_decl.lbrace_token, .Newline); // {
1275
1276 // ais.pushIndent();
1277 // defer ais.popIndent();
1278
1279 // for (fields_and_decls) |decl, i| {
1280 // const space_after_decl: Space = if (i + 1 >= fields_and_decls.len) .Newline else .Space;
1281 // try renderContainerDecl(allocator, ais, tree, decl, space_after_decl);
1282 // }
1283 // } else {
1284 // // All the declarations on the same line
1285 // try renderToken(ais, tree, container_decl.lbrace_token, .Space); // {
1286
1287 // for (fields_and_decls) |decl| {
1288 // try renderContainerDecl(allocator, ais, tree, decl, .Space);
1289 // }
1290 // }
1291
1292 // return renderToken(ais, tree, container_decl.rbrace_token, space); // }
1293 //},
1294
1295 //.ErrorSetDecl => {
1296 // const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
1297
1298 // const lbrace = tree.nextToken(err_set_decl.error_token);
1299
1300 // if (err_set_decl.decls_len == 0) {
1301 // try renderToken(ais, tree, err_set_decl.error_token, Space.None);
1302 // try renderToken(ais, tree, lbrace, Space.None);
1303 // return renderToken(ais, tree, err_set_decl.rbrace_token, space);
1304 // }
1305
1306 // if (err_set_decl.decls_len == 1) blk: {
1307 // const node = err_set_decl.decls()[0];
1308
1309 // // if there are any doc comments or same line comments
1310 // // don't try to put it all on one line
1311 // if (node.cast(ast.Node.ErrorTag)) |tag| {
1312 // if (tag.doc_comments != null) break :blk;
1313 // } else {
1314 // break :blk;
1315 // }
1316
1317 // try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
1318 // try renderToken(ais, tree, lbrace, Space.None); // {
1319 // try renderExpression(allocator, ais, tree, node, Space.None);
1320 // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // }
1321 // }
1322
1323 // try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
1324
1325 // const src_has_trailing_comma = blk: {
1326 // const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
1327 // break :blk tree.token_tags[maybe_comma] == .Comma;
1328 // };
1329
1330 // if (src_has_trailing_comma) {
1331 // {
1332 // ais.pushIndent();
1333 // defer ais.popIndent();
1334
1335 // try renderToken(ais, tree, lbrace, Space.Newline); // {
1336 // const decls = err_set_decl.decls();
1337 // for (decls) |node, i| {
1338 // if (i + 1 < decls.len) {
1339 // try renderExpression(allocator, ais, tree, node, Space.None);
1340 // try renderToken(ais, tree, tree.nextToken(node.lastToken()), Space.Newline); // ,
1341
1342 // try renderExtraNewline(tree, ais, decls[i + 1]);
1343 // } else {
1344 // try renderExpression(allocator, ais, tree, node, Space.Comma);
1345 // }
1346 // }
1347 // }
1348
1349 // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // }
1350 // } else {
1351 // try renderToken(ais, tree, lbrace, Space.Space); // {
1352
1353 // const decls = err_set_decl.decls();
1354 // for (decls) |node, i| {
1355 // if (i + 1 < decls.len) {
1356 // try renderExpression(allocator, ais, tree, node, Space.None);
1357
1358 // const comma_token = tree.nextToken(node.lastToken());
1359 // assert(tree.token_tags[comma_token] == .Comma);
1360 // try renderToken(ais, tree, comma_token, Space.Space); // ,
1361 // try renderExtraNewline(tree, ais, decls[i + 1]);
1362 // } else {
1363 // try renderExpression(allocator, ais, tree, node, Space.Space);
1364 // }
1365 // }
1366
1367 // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // }
1368 // }
1369 //},
1370
1371 //.ErrorTag => {
1372 // const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
1373
1374 // try renderDocComments(tree, ais, tag, tag.doc_comments);
1375 // return renderToken(ais, tree, tag.name_token, space); // name
1376 //},
1377
1378 //.MultilineStringLiteral => {
1379 // const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
1380
1381 // {
1382 // const locked_indents = ais.lockOneShotIndent();
1383 // defer {
1384 // var i: u8 = 0;
1385 // while (i < locked_indents) : (i += 1) ais.popIndent();
1386 // }
1387 // try ais.maybeInsertNewline();
1388
1389 // for (multiline_str_literal.lines()) |t| try renderToken(ais, tree, t, Space.None);
1390 // }
1391 //},
1392
1393 //.BuiltinCall => {
1394 // const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
1395
1396 // // TODO remove after 0.7.0 release
1397 // if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
1398 // return ais.writer().writeAll("opaque {}");
1399
1400 // // TODO remove after 0.7.0 release
1401 // {
1402 // const params = builtin_call.paramsConst();
1403 // if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
1404 // params.len == 1)
1405 // {
1406 // if (params[0].castTag(.EnumLiteral)) |enum_literal|
1407 // if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
1408 // return ais.writer().writeAll("opaque {}");
1409 // }
1410 // }
1411
1412 // try renderToken(ais, tree, builtin_call.builtin_token, Space.None); // @name
1413
1414 // const src_params_trailing_comma = blk: {
1415 // if (builtin_call.params_len == 0) break :blk false;
1416 // const last_node = builtin_call.params()[builtin_call.params_len - 1];
1417 // const maybe_comma = tree.nextToken(last_node.lastToken());
1418 // break :blk tree.token_tags[maybe_comma] == .Comma;
1419 // };
1420
1421 // const lparen = tree.nextToken(builtin_call.builtin_token);
1422
1423 // if (!src_params_trailing_comma) {
1424 // try renderToken(ais, tree, lparen, Space.None); // (
1425
1426 // // render all on one line, no trailing comma
1427 // const params = builtin_call.params();
1428 // for (params) |param_node, i| {
1429 // const maybe_comment = param_node.firstToken() - 1;
1430 // if (param_node.*.tag == .MultilineStringLiteral or tree.token_tags[maybe_comment] == .LineComment) {
1431 // ais.pushIndentOneShot();
1432 // }
1433 // try renderExpression(allocator, ais, tree, param_node, Space.None);
1434
1435 // if (i + 1 < params.len) {
1436 // const comma_token = tree.nextToken(param_node.lastToken());
1437 // try renderToken(ais, tree, comma_token, Space.Space); // ,
1438 // }
1439 // }
1440 // } else {
1441 // // one param per line
1442 // ais.pushIndent();
1443 // defer ais.popIndent();
1444 // try renderToken(ais, tree, lparen, Space.Newline); // (
1445
1446 // for (builtin_call.params()) |param_node| {
1447 // try renderExpression(allocator, ais, tree, param_node, Space.Comma);
1448 // }
1449 // }
1450
1451 // return renderToken(ais, tree, builtin_call.rparen_token, space); // )
1452 //},
1453
1454 //.FnProto => {
1455 // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base);
1456
1457 // if (fn_proto.getVisibToken()) |visib_token_index| {
1458 // const visib_token = tree.token_tags[visib_token_index];
1459 // assert(visib_token == .Keyword_pub or visib_token == .Keyword_export);
1460
1461 // try renderToken(ais, tree, visib_token_index, Space.Space); // pub
1462 // }
1463
1464 // if (fn_proto.getExternExportInlineToken()) |extern_export_inline_token| {
1465 // if (fn_proto.getIsExternPrototype() == null)
1466 // try renderToken(ais, tree, extern_export_inline_token, Space.Space); // extern/export/inline
1467 // }
1468
1469 // if (fn_proto.getLibName()) |lib_name| {
1470 // try renderExpression(allocator, ais, tree, lib_name, Space.Space);
1471 // }
1472
1473 // const lparen = if (fn_proto.getNameToken()) |name_token| blk: {
1474 // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn
1475 // try renderToken(ais, tree, name_token, Space.None); // name
1476 // break :blk tree.nextToken(name_token);
1477 // } else blk: {
1478 // try renderToken(ais, tree, fn_proto.fn_token, Space.Space); // fn
1479 // break :blk tree.nextToken(fn_proto.fn_token);
1480 // };
1481 // assert(tree.token_tags[lparen] == .LParen);
1482
1483 // const rparen = tree.prevToken(
1484 // // the first token for the annotation expressions is the left
1485 // // parenthesis, hence the need for two prevToken
1486 // if (fn_proto.getAlignExpr()) |align_expr|
1487 // tree.prevToken(tree.prevToken(align_expr.firstToken()))
1488 // else if (fn_proto.getSectionExpr()) |section_expr|
1489 // tree.prevToken(tree.prevToken(section_expr.firstToken()))
1490 // else if (fn_proto.getCallconvExpr()) |callconv_expr|
1491 // tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
1492 // else switch (fn_proto.return_type) {
1493 // .Explicit => |node| node.firstToken(),
1494 // .InferErrorSet => |node| tree.prevToken(node.firstToken()),
1495 // .Invalid => unreachable,
1496 // },
1497 // );
1498 // assert(tree.token_tags[rparen] == .RParen);
1499
1500 // const src_params_trailing_comma = blk: {
1501 // const maybe_comma = tree.token_tags[rparen - 1];
1502 // break :blk maybe_comma == .Comma or maybe_comma == .LineComment;
1503 // };
1504
1505 // if (!src_params_trailing_comma) {
1506 // try renderToken(ais, tree, lparen, Space.None); // (
1507
1508 // // render all on one line, no trailing comma
1509 // for (fn_proto.params()) |param_decl, i| {
1510 // try renderParamDecl(allocator, ais, tree, param_decl, Space.None);
1511
1512 // if (i + 1 < fn_proto.params_len or fn_proto.getVarArgsToken() != null) {
1513 // const comma = tree.nextToken(param_decl.lastToken());
1514 // try renderToken(ais, tree, comma, Space.Space); // ,
1515 // }
1516 // }
1517 // if (fn_proto.getVarArgsToken()) |var_args_token| {
1518 // try renderToken(ais, tree, var_args_token, Space.None);
1519 // }
1520 // } else {
1521 // // one param per line
1522 // ais.pushIndent();
1523 // defer ais.popIndent();
1524 // try renderToken(ais, tree, lparen, Space.Newline); // (
1525
1526 // for (fn_proto.params()) |param_decl| {
1527 // try renderParamDecl(allocator, ais, tree, param_decl, Space.Comma);
1528 // }
1529 // if (fn_proto.getVarArgsToken()) |var_args_token| {
1530 // try renderToken(ais, tree, var_args_token, Space.Comma);
1531 // }
1532 // }
1533
1534 // try renderToken(ais, tree, rparen, Space.Space); // )
1535
1536 // if (fn_proto.getAlignExpr()) |align_expr| {
1537 // const align_rparen = tree.nextToken(align_expr.lastToken());
1538 // const align_lparen = tree.prevToken(align_expr.firstToken());
1539 // const align_kw = tree.prevToken(align_lparen);
1540
1541 // try renderToken(ais, tree, align_kw, Space.None); // align
1542 // try renderToken(ais, tree, align_lparen, Space.None); // (
1543 // try renderExpression(allocator, ais, tree, align_expr, Space.None);
1544 // try renderToken(ais, tree, align_rparen, Space.Space); // )
1545 // }
1546
1547 // if (fn_proto.getSectionExpr()) |section_expr| {
1548 // const section_rparen = tree.nextToken(section_expr.lastToken());
1549 // const section_lparen = tree.prevToken(section_expr.firstToken());
1550 // const section_kw = tree.prevToken(section_lparen);
1551
1552 // try renderToken(ais, tree, section_kw, Space.None); // section
1553 // try renderToken(ais, tree, section_lparen, Space.None); // (
1554 // try renderExpression(allocator, ais, tree, section_expr, Space.None);
1555 // try renderToken(ais, tree, section_rparen, Space.Space); // )
1556 // }
1557
1558 // if (fn_proto.getCallconvExpr()) |callconv_expr| {
1559 // const callconv_rparen = tree.nextToken(callconv_expr.lastToken());
1560 // const callconv_lparen = tree.prevToken(callconv_expr.firstToken());
1561 // const callconv_kw = tree.prevToken(callconv_lparen);
1562
1563 // try renderToken(ais, tree, callconv_kw, Space.None); // callconv
1564 // try renderToken(ais, tree, callconv_lparen, Space.None); // (
1565 // try renderExpression(allocator, ais, tree, callconv_expr, Space.None);
1566 // try renderToken(ais, tree, callconv_rparen, Space.Space); // )
1567 // } else if (fn_proto.getIsExternPrototype() != null) {
1568 // try ais.writer().writeAll("callconv(.C) ");
1569 // } else if (fn_proto.getIsAsync() != null) {
1570 // try ais.writer().writeAll("callconv(.Async) ");
1571 // }
1572
1573 // switch (fn_proto.return_type) {
1574 // .Explicit => |node| {
1575 // return renderExpression(allocator, ais, tree, node, space);
1576 // },
1577 // .InferErrorSet => |node| {
1578 // try renderToken(ais, tree, tree.prevToken(node.firstToken()), Space.None); // !
1579 // return renderExpression(allocator, ais, tree, node, space);
1580 // },
1581 // .Invalid => unreachable,
1582 // }
1583 //},
1584
1585 //.AnyFrameType => {
1586 // const anyframe_type = @fieldParentPtr(ast.Node.AnyFrameType, "base", base);
1587
1588 // if (anyframe_type.result) |result| {
1589 // try renderToken(ais, tree, anyframe_type.anyframe_token, Space.None); // anyframe
1590 // try renderToken(ais, tree, result.arrow_token, Space.None); // ->
1591 // return renderExpression(allocator, ais, tree, result.return_type, space);
1592 // } else {
1593 // return renderToken(ais, tree, anyframe_type.anyframe_token, space); // anyframe
1594 // }
1595 //},
1596
1597 //.DocComment => unreachable, // doc comments are attached to nodes
1598
1599 //.Switch => {
1600 // const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
1601
1602 // try renderToken(ais, tree, switch_node.switch_token, Space.Space); // switch
1603 // try renderToken(ais, tree, tree.nextToken(switch_node.switch_token), Space.None); // (
1604
1605 // const rparen = tree.nextToken(switch_node.expr.lastToken());
1606 // const lbrace = tree.nextToken(rparen);
1607
1608 // if (switch_node.cases_len == 0) {
1609 // try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
1610 // try renderToken(ais, tree, rparen, Space.Space); // )
1611 // try renderToken(ais, tree, lbrace, Space.None); // {
1612 // return renderToken(ais, tree, switch_node.rbrace, space); // }
1613 // }
1614
1615 // try renderExpression(allocator, ais, tree, switch_node.expr, Space.None);
1616 // try renderToken(ais, tree, rparen, Space.Space); // )
1617
1618 // {
1619 // ais.pushIndentNextLine();
1620 // defer ais.popIndent();
1621 // try renderToken(ais, tree, lbrace, Space.Newline); // {
1622
1623 // const cases = switch_node.cases();
1624 // for (cases) |node, i| {
1625 // try renderExpression(allocator, ais, tree, node, Space.Comma);
1626
1627 // if (i + 1 < cases.len) {
1628 // try renderExtraNewline(tree, ais, cases[i + 1]);
1629 // }
1630 // }
1631 // }
1632
1633 // return renderToken(ais, tree, switch_node.rbrace, space); // }
1634 //},
1635
1636 //.SwitchCase => {
1637 // const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
1638
1639 // assert(switch_case.items_len != 0);
1640 // const src_has_trailing_comma = blk: {
1641 // const last_node = switch_case.items()[switch_case.items_len - 1];
1642 // const maybe_comma = tree.nextToken(last_node.lastToken());
1643 // break :blk tree.token_tags[maybe_comma] == .Comma;
1644 // };
1645
1646 // if (switch_case.items_len == 1 or !src_has_trailing_comma) {
1647 // const items = switch_case.items();
1648 // for (items) |node, i| {
1649 // if (i + 1 < items.len) {
1650 // try renderExpression(allocator, ais, tree, node, Space.None);
1651
1652 // const comma_token = tree.nextToken(node.lastToken());
1653 // try renderToken(ais, tree, comma_token, Space.Space); // ,
1654 // try renderExtraNewline(tree, ais, items[i + 1]);
1655 // } else {
1656 // try renderExpression(allocator, ais, tree, node, Space.Space);
1657 // }
1658 // }
1659 // } else {
1660 // const items = switch_case.items();
1661 // for (items) |node, i| {
1662 // if (i + 1 < items.len) {
1663 // try renderExpression(allocator, ais, tree, node, Space.None);
1664
1665 // const comma_token = tree.nextToken(node.lastToken());
1666 // try renderToken(ais, tree, comma_token, Space.Newline); // ,
1667 // try renderExtraNewline(tree, ais, items[i + 1]);
1668 // } else {
1669 // try renderExpression(allocator, ais, tree, node, Space.Comma);
1670 // }
1671 // }
1672 // }
1673
1674 // try renderToken(ais, tree, switch_case.arrow_token, Space.Space); // =>
1675
1676 // if (switch_case.payload) |payload| {
1677 // try renderExpression(allocator, ais, tree, payload, Space.Space);
1678 // }
1679
1680 // return renderExpression(allocator, ais, tree, switch_case.expr, space);
1681 //},
1682 //.SwitchElse => {
1683 // const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
1684 // return renderToken(ais, tree, switch_else.token, space);
1685 //},
1686 //.Else => {
1687 // const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
1688
1689 // const body_is_block = nodeIsBlock(else_node.body);
1690 // const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
1691
1692 // const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
1693 // try renderToken(ais, tree, else_node.else_token, after_else_space);
1694
1695 // if (else_node.payload) |payload| {
1696 // const payload_space = if (same_line) Space.Space else Space.Newline;
1697 // try renderExpression(allocator, ais, tree, payload, payload_space);
1698 // }
1699
1700 // if (same_line) {
1701 // return renderExpression(allocator, ais, tree, else_node.body, space);
1702 // } else {
1703 // ais.pushIndent();
1704 // defer ais.popIndent();
1705 // return renderExpression(allocator, ais, tree, else_node.body, space);
1706 // }
1707 //},
1708
1709 //.While => {
1710 // const while_node = @fieldParentPtr(ast.Node.While, "base", base);
1711
1712 // if (while_node.label) |label| {
1713 // try renderToken(ais, tree, label, Space.None); // label
1714 // try renderToken(ais, tree, tree.nextToken(label), Space.Space); // :
1715 // }
1716
1717 // if (while_node.inline_token) |inline_token| {
1718 // try renderToken(ais, tree, inline_token, Space.Space); // inline
1719 // }
1720
1721 // try renderToken(ais, tree, while_node.while_token, Space.Space); // while
1722 // try renderToken(ais, tree, tree.nextToken(while_node.while_token), Space.None); // (
1723 // try renderExpression(allocator, ais, tree, while_node.condition, Space.None);
1724
1725 // const cond_rparen = tree.nextToken(while_node.condition.lastToken());
1726
1727 // const body_is_block = nodeIsBlock(while_node.body);
1728
1729 // var block_start_space: Space = undefined;
1730 // var after_body_space: Space = undefined;
1731
1732 // if (body_is_block) {
1733 // block_start_space = Space.BlockStart;
1734 // after_body_space = if (while_node.@"else" == null) space else Space.SpaceOrOutdent;
1735 // } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
1736 // block_start_space = Space.Space;
1737 // after_body_space = if (while_node.@"else" == null) space else Space.Space;
1738 // } else {
1739 // block_start_space = Space.Newline;
1740 // after_body_space = if (while_node.@"else" == null) space else Space.Newline;
1741 // }
1742
1743 // {
1744 // const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
1745 // try renderToken(ais, tree, cond_rparen, rparen_space); // )
1746 // }
1747
1748 // if (while_node.payload) |payload| {
1749 // const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
1750 // try renderExpression(allocator, ais, tree, payload, payload_space);
1751 // }
1752
1753 // if (while_node.continue_expr) |continue_expr| {
1754 // const rparen = tree.nextToken(continue_expr.lastToken());
1755 // const lparen = tree.prevToken(continue_expr.firstToken());
1756 // const colon = tree.prevToken(lparen);
1757
1758 // try renderToken(ais, tree, colon, Space.Space); // :
1759 // try renderToken(ais, tree, lparen, Space.None); // (
1760
1761 // try renderExpression(allocator, ais, tree, continue_expr, Space.None);
1762
1763 // try renderToken(ais, tree, rparen, block_start_space); // )
1764 // }
1765
1766 // {
1767 // if (!body_is_block) ais.pushIndent();
1768 // defer if (!body_is_block) ais.popIndent();
1769 // try renderExpression(allocator, ais, tree, while_node.body, after_body_space);
1770 // }
1771
1772 // if (while_node.@"else") |@"else"| {
1773 // return renderExpression(allocator, ais, tree, &@"else".base, space);
1774 // }
1775 //},
1776
1777 //.For => {
1778 // const for_node = @fieldParentPtr(ast.Node.For, "base", base);
1779
1780 // if (for_node.label) |label| {
1781 // try renderToken(ais, tree, label, Space.None); // label
1782 // try renderToken(ais, tree, tree.nextToken(label), Space.Space); // :
1783 // }
1784
1785 // if (for_node.inline_token) |inline_token| {
1786 // try renderToken(ais, tree, inline_token, Space.Space); // inline
1787 // }
1788
1789 // try renderToken(ais, tree, for_node.for_token, Space.Space); // for
1790 // try renderToken(ais, tree, tree.nextToken(for_node.for_token), Space.None); // (
1791 // try renderExpression(allocator, ais, tree, for_node.array_expr, Space.None);
1792
1793 // const rparen = tree.nextToken(for_node.array_expr.lastToken());
1794
1795 // const body_is_block = for_node.body.tag.isBlock();
1796 // const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());
1797 // const body_on_same_line = body_is_block or src_one_line_to_body;
1798
1799 // try renderToken(ais, tree, rparen, Space.Space); // )
1800
1801 // const space_after_payload = if (body_on_same_line) Space.Space else Space.Newline;
1802 // try renderExpression(allocator, ais, tree, for_node.payload, space_after_payload); // |x|
1803
1804 // const space_after_body = blk: {
1805 // if (for_node.@"else") |@"else"| {
1806 // const src_one_line_to_else = tree.tokensOnSameLine(rparen, @"else".firstToken());
1807 // if (body_is_block or src_one_line_to_else) {
1808 // break :blk Space.Space;
1809 // } else {
1810 // break :blk Space.Newline;
1811 // }
1812 // } else {
1813 // break :blk space;
1814 // }
1815 // };
1816
1817 // {
1818 // if (!body_on_same_line) ais.pushIndent();
1819 // defer if (!body_on_same_line) ais.popIndent();
1820 // try renderExpression(allocator, ais, tree, for_node.body, space_after_body); // { body }
1821 // }
1822
1823 // if (for_node.@"else") |@"else"| {
1824 // return renderExpression(allocator, ais, tree, &@"else".base, space); // else
1825 // }
1826 //},
1827
1828 //.If => {
1829 // const if_node = @fieldParentPtr(ast.Node.If, "base", base);
1830
1831 // const lparen = tree.nextToken(if_node.if_token);
1832 // const rparen = tree.nextToken(if_node.condition.lastToken());
1833
1834 // try renderToken(ais, tree, if_node.if_token, Space.Space); // if
1835 // try renderToken(ais, tree, lparen, Space.None); // (
1836
1837 // try renderExpression(allocator, ais, tree, if_node.condition, Space.None); // condition
1838
1839 // const body_is_if_block = if_node.body.tag == .If;
1840 // const body_is_block = nodeIsBlock(if_node.body);
1841
1842 // if (body_is_if_block) {
1843 // try renderExtraNewline(tree, ais, if_node.body);
1844 // } else if (body_is_block) {
1845 // const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
1846 // try renderToken(ais, tree, rparen, after_rparen_space); // )
1847
1848 // if (if_node.payload) |payload| {
1849 // try renderExpression(allocator, ais, tree, payload, Space.BlockStart); // |x|
1850 // }
1851
1852 // if (if_node.@"else") |@"else"| {
1853 // try renderExpression(allocator, ais, tree, if_node.body, Space.SpaceOrOutdent);
1854 // return renderExpression(allocator, ais, tree, &@"else".base, space);
1855 // } else {
1856 // return renderExpression(allocator, ais, tree, if_node.body, space);
1857 // }
1858 // }
1859
1860 // const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken());
1861
1862 // if (src_has_newline) {
1863 // const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space;
1864
1865 // {
1866 // ais.pushIndent();
1867 // defer ais.popIndent();
1868 // try renderToken(ais, tree, rparen, after_rparen_space); // )
1869 // }
1870
1871 // if (if_node.payload) |payload| {
1872 // try renderExpression(allocator, ais, tree, payload, Space.Newline);
1873 // }
1874
1875 // if (if_node.@"else") |@"else"| {
1876 // const else_is_block = nodeIsBlock(@"else".body);
1877
1878 // {
1879 // ais.pushIndent();
1880 // defer ais.popIndent();
1881 // try renderExpression(allocator, ais, tree, if_node.body, Space.Newline);
1882 // }
1883
1884 // if (else_is_block) {
1885 // try renderToken(ais, tree, @"else".else_token, Space.Space); // else
1886
1887 // if (@"else".payload) |payload| {
1888 // try renderExpression(allocator, ais, tree, payload, Space.Space);
1889 // }
1890
1891 // return renderExpression(allocator, ais, tree, @"else".body, space);
1892 // } else {
1893 // const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;
1894 // try renderToken(ais, tree, @"else".else_token, after_else_space); // else
1895
1896 // if (@"else".payload) |payload| {
1897 // try renderExpression(allocator, ais, tree, payload, Space.Newline);
1898 // }
1899
1900 // ais.pushIndent();
1901 // defer ais.popIndent();
1902 // return renderExpression(allocator, ais, tree, @"else".body, space);
1903 // }
1904 // } else {
1905 // ais.pushIndent();
1906 // defer ais.popIndent();
1907 // return renderExpression(allocator, ais, tree, if_node.body, space);
1908 // }
1909 // }
1910
1911 // // Single line if statement
1912
1913 // try renderToken(ais, tree, rparen, Space.Space); // )
1914
1915 // if (if_node.payload) |payload| {
1916 // try renderExpression(allocator, ais, tree, payload, Space.Space);
1917 // }
1918
1919 // if (if_node.@"else") |@"else"| {
1920 // try renderExpression(allocator, ais, tree, if_node.body, Space.Space);
1921 // try renderToken(ais, tree, @"else".else_token, Space.Space);
1922
1923 // if (@"else".payload) |payload| {
1924 // try renderExpression(allocator, ais, tree, payload, Space.Space);
1925 // }
1926
1927 // return renderExpression(allocator, ais, tree, @"else".body, space);
1928 // } else {
1929 // return renderExpression(allocator, ais, tree, if_node.body, space);
1930 // }
1931 //},
1932
1933 //.Asm => {
1934 // const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
1935
1936 // try renderToken(ais, tree, asm_node.asm_token, Space.Space); // asm
1937
1938 // if (asm_node.volatile_token) |volatile_token| {
1939 // try renderToken(ais, tree, volatile_token, Space.Space); // volatile
1940 // try renderToken(ais, tree, tree.nextToken(volatile_token), Space.None); // (
1941 // } else {
1942 // try renderToken(ais, tree, tree.nextToken(asm_node.asm_token), Space.None); // (
1943 // }
1944
1945 // asmblk: {
1946 // ais.pushIndent();
1947 // defer ais.popIndent();
1948
1949 // if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1950 // try renderExpression(allocator, ais, tree, asm_node.template, Space.None);
1951 // break :asmblk;
1952 // }
1953
1954 // try renderExpression(allocator, ais, tree, asm_node.template, Space.Newline);
1955
1956 // ais.setIndentDelta(asm_indent_delta);
1957 // defer ais.setIndentDelta(indent_delta);
1958
1959 // const colon1 = tree.nextToken(asm_node.template.lastToken());
1960
1961 // const colon2 = if (asm_node.outputs.len == 0) blk: {
1962 // try renderToken(ais, tree, colon1, Space.Newline); // :
1963
1964 // break :blk tree.nextToken(colon1);
1965 // } else blk: {
1966 // try renderToken(ais, tree, colon1, Space.Space); // :
1967
1968 // ais.pushIndent();
1969 // defer ais.popIndent();
1970
1971 // for (asm_node.outputs) |*asm_output, i| {
1972 // if (i + 1 < asm_node.outputs.len) {
1973 // const next_asm_output = asm_node.outputs[i + 1];
1974 // try renderAsmOutput(allocator, ais, tree, asm_output, Space.None);
1975
1976 // const comma = tree.prevToken(next_asm_output.firstToken());
1977 // try renderToken(ais, tree, comma, Space.Newline); // ,
1978 // try renderExtraNewlineToken(tree, ais, next_asm_output.firstToken());
1979 // } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1980 // try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
1981 // break :asmblk;
1982 // } else {
1983 // try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline);
1984 // const comma_or_colon = tree.nextToken(asm_output.lastToken());
1985 // break :blk switch (tree.token_tags[comma_or_colon]) {
1986 // .Comma => tree.nextToken(comma_or_colon),
1987 // else => comma_or_colon,
1988 // };
1989 // }
1990 // }
1991 // unreachable;
1992 // };
1993
1994 // const colon3 = if (asm_node.inputs.len == 0) blk: {
1995 // try renderToken(ais, tree, colon2, Space.Newline); // :
1996 // break :blk tree.nextToken(colon2);
1997 // } else blk: {
1998 // try renderToken(ais, tree, colon2, Space.Space); // :
1999 // ais.pushIndent();
2000 // defer ais.popIndent();
2001 // for (asm_node.inputs) |*asm_input, i| {
2002 // if (i + 1 < asm_node.inputs.len) {
2003 // const next_asm_input = &asm_node.inputs[i + 1];
2004 // try renderAsmInput(allocator, ais, tree, asm_input, Space.None);
2005
2006 // const comma = tree.prevToken(next_asm_input.firstToken());
2007 // try renderToken(ais, tree, comma, Space.Newline); // ,
2008 // try renderExtraNewlineToken(tree, ais, next_asm_input.firstToken());
2009 // } else if (asm_node.clobbers.len == 0) {
2010 // try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
2011 // break :asmblk;
2012 // } else {
2013 // try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline);
2014 // const comma_or_colon = tree.nextToken(asm_input.lastToken());
2015 // break :blk switch (tree.token_tags[comma_or_colon]) {
2016 // .Comma => tree.nextToken(comma_or_colon),
2017 // else => comma_or_colon,
2018 // };
2019 // }
2020 // }
2021 // unreachable;
2022 // };
2023
2024 // try renderToken(ais, tree, colon3, Space.Space); // :
2025 // ais.pushIndent();
2026 // defer ais.popIndent();
2027 // for (asm_node.clobbers) |clobber_node, i| {
2028 // if (i + 1 >= asm_node.clobbers.len) {
2029 // try renderExpression(allocator, ais, tree, clobber_node, Space.Newline);
2030 // break :asmblk;
2031 // } else {
2032 // try renderExpression(allocator, ais, tree, clobber_node, Space.None);
2033 // const comma = tree.nextToken(clobber_node.lastToken());
2034 // try renderToken(ais, tree, comma, Space.Space); // ,
2035 // }
2036 // }
2037 // }
2038
2039 // return renderToken(ais, tree, asm_node.rparen, space);
2040 //},
2041
2042 //.EnumLiteral => {
2043 // const enum_literal = @fieldParentPtr(ast.Node.EnumLiteral, "base", base);
2044
2045 // try renderToken(ais, tree, enum_literal.dot, Space.None); // .
2046 // return renderToken(ais, tree, enum_literal.name, space); // name
2047 //},
2048
2049 //.ContainerField,
2050 //.Root,
2051 //.VarDecl,
2052 //.Use,
2053 //.TestDecl,
2054 //=> unreachable,
2055 else => @panic("TODO implement more renderExpression"),
2151 }2056 }
2152}2057}
21532058
2154fn renderArrayType(2059fn renderArrayType(
2155 allocator: *mem.Allocator,2060 allocator: *mem.Allocator,
2156 ais: anytype,2061 ais: *Ais,
2157 tree: *ast.Tree,2062 tree: ast.Tree,
2158 lbracket: ast.TokenIndex,2063 lbracket: ast.TokenIndex,
2159 rhs: *ast.Node,2064 rhs: ast.Node.Index,
2160 len_expr: *ast.Node,2065 len_expr: ast.Node.Index,
2161 opt_sentinel: ?*ast.Node,2066 opt_sentinel: ?ast.Node.Index,
2162 space: Space,2067 space: Space,
2163) (@TypeOf(ais.*).Error || Error)!void {2068) Error!void {
2164 const rbracket = tree.nextToken(if (opt_sentinel) |sentinel|2069 const rbracket = tree.nextToken(if (opt_sentinel) |sentinel|
2165 sentinel.lastToken()2070 sentinel.lastToken()
2166 else2071 else
2167 len_expr.lastToken());2072 len_expr.lastToken());
21682073
2169 const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment;2074 const starts_with_comment = tree.token_tags[lbracket + 1] == .LineComment;
2170 const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment;2075 const ends_with_comment = tree.token_tags[rbracket - 1] == .LineComment;
2171 const new_space = if (ends_with_comment) Space.Newline else Space.None;2076 const new_space = if (ends_with_comment) Space.Newline else Space.None;
2172 {2077 {
2173 const do_indent = (starts_with_comment or ends_with_comment);2078 const do_indent = (starts_with_comment or ends_with_comment);
2174 if (do_indent) ais.pushIndent();2079 if (do_indent) ais.pushIndent();
2175 defer if (do_indent) ais.popIndent();2080 defer if (do_indent) ais.popIndent();
21762081
2177 try renderToken(tree, ais, lbracket, Space.None); // [2082 try renderToken(ais, tree, lbracket, Space.None); // [
2178 try renderExpression(allocator, ais, tree, len_expr, new_space);2083 try renderExpression(allocator, ais, tree, len_expr, new_space);
21792084
2180 if (starts_with_comment) {2085 if (starts_with_comment) {
...@@ -2182,25 +2087,25 @@ fn renderArrayType(...@@ -2182,25 +2087,25 @@ fn renderArrayType(
2182 }2087 }
2183 if (opt_sentinel) |sentinel| {2088 if (opt_sentinel) |sentinel| {
2184 const colon_token = tree.prevToken(sentinel.firstToken());2089 const colon_token = tree.prevToken(sentinel.firstToken());
2185 try renderToken(tree, ais, colon_token, Space.None); // :2090 try renderToken(ais, tree, colon_token, Space.None); // :
2186 try renderExpression(allocator, ais, tree, sentinel, Space.None);2091 try renderExpression(allocator, ais, tree, sentinel, Space.None);
2187 }2092 }
2188 if (starts_with_comment) {2093 if (starts_with_comment) {
2189 try ais.maybeInsertNewline();2094 try ais.maybeInsertNewline();
2190 }2095 }
2191 }2096 }
2192 try renderToken(tree, ais, rbracket, Space.None); // ]2097 try renderToken(ais, tree, rbracket, Space.None); // ]
21932098
2194 return renderExpression(allocator, ais, tree, rhs, space);2099 return renderExpression(allocator, ais, tree, rhs, space);
2195}2100}
21962101
2197fn renderAsmOutput(2102fn renderAsmOutput(
2198 allocator: *mem.Allocator,2103 allocator: *mem.Allocator,
2199 ais: anytype,2104 ais: *Ais,
2200 tree: *ast.Tree,2105 tree: ast.Tree,
2201 asm_output: *const ast.Node.Asm.Output,2106 asm_output: *const ast.Node.Asm.Output,
2202 space: Space,2107 space: Space,
2203) (@TypeOf(ais.*).Error || Error)!void {2108) Error!void {
2204 try ais.writer().writeAll("[");2109 try ais.writer().writeAll("[");
2205 try renderExpression(allocator, ais, tree, asm_output.symbolic_name, Space.None);2110 try renderExpression(allocator, ais, tree, asm_output.symbolic_name, Space.None);
2206 try ais.writer().writeAll("] ");2111 try ais.writer().writeAll("] ");
...@@ -2217,37 +2122,37 @@ fn renderAsmOutput(...@@ -2217,37 +2122,37 @@ fn renderAsmOutput(
2217 },2122 },
2218 }2123 }
22192124
2220 return renderToken(tree, ais, asm_output.lastToken(), space); // )2125 return renderToken(ais, tree, asm_output.lastToken(), space); // )
2221}2126}
22222127
2223fn renderAsmInput(2128fn renderAsmInput(
2224 allocator: *mem.Allocator,2129 allocator: *mem.Allocator,
2225 ais: anytype,2130 ais: *Ais,
2226 tree: *ast.Tree,2131 tree: ast.Tree,
2227 asm_input: *const ast.Node.Asm.Input,2132 asm_input: *const ast.Node.Asm.Input,
2228 space: Space,2133 space: Space,
2229) (@TypeOf(ais.*).Error || Error)!void {2134) Error!void {
2230 try ais.writer().writeAll("[");2135 try ais.writer().writeAll("[");
2231 try renderExpression(allocator, ais, tree, asm_input.symbolic_name, Space.None);2136 try renderExpression(allocator, ais, tree, asm_input.symbolic_name, Space.None);
2232 try ais.writer().writeAll("] ");2137 try ais.writer().writeAll("] ");
2233 try renderExpression(allocator, ais, tree, asm_input.constraint, Space.None);2138 try renderExpression(allocator, ais, tree, asm_input.constraint, Space.None);
2234 try ais.writer().writeAll(" (");2139 try ais.writer().writeAll(" (");
2235 try renderExpression(allocator, ais, tree, asm_input.expr, Space.None);2140 try renderExpression(allocator, ais, tree, asm_input.expr, Space.None);
2236 return renderToken(tree, ais, asm_input.lastToken(), space); // )2141 return renderToken(ais, tree, asm_input.lastToken(), space); // )
2237}2142}
22382143
2239fn renderVarDecl(2144fn renderVarDecl(
2240 allocator: *mem.Allocator,2145 allocator: *mem.Allocator,
2241 ais: anytype,2146 ais: *Ais,
2242 tree: *ast.Tree,2147 tree: ast.Tree,
2243 var_decl: *ast.Node.VarDecl,2148 var_decl: ast.Node.Index.VarDecl,
2244) (@TypeOf(ais.*).Error || Error)!void {2149) Error!void {
2245 if (var_decl.getVisibToken()) |visib_token| {2150 if (var_decl.getVisibToken()) |visib_token| {
2246 try renderToken(tree, ais, visib_token, Space.Space); // pub2151 try renderToken(ais, tree, visib_token, Space.Space); // pub
2247 }2152 }
22482153
2249 if (var_decl.getExternExportToken()) |extern_export_token| {2154 if (var_decl.getExternExportToken()) |extern_export_token| {
2250 try renderToken(tree, ais, extern_export_token, Space.Space); // extern2155 try renderToken(ais, tree, extern_export_token, Space.Space); // extern
22512156
2252 if (var_decl.getLibName()) |lib_name| {2157 if (var_decl.getLibName()) |lib_name| {
2253 try renderExpression(allocator, ais, tree, lib_name, Space.Space); // "lib"2158 try renderExpression(allocator, ais, tree, lib_name, Space.Space); // "lib"
...@@ -2255,13 +2160,13 @@ fn renderVarDecl(...@@ -2255,13 +2160,13 @@ fn renderVarDecl(
2255 }2160 }
22562161
2257 if (var_decl.getComptimeToken()) |comptime_token| {2162 if (var_decl.getComptimeToken()) |comptime_token| {
2258 try renderToken(tree, ais, comptime_token, Space.Space); // comptime2163 try renderToken(ais, tree, comptime_token, Space.Space); // comptime
2259 }2164 }
22602165
2261 if (var_decl.getThreadLocalToken()) |thread_local_token| {2166 if (var_decl.getThreadLocalToken()) |thread_local_token| {
2262 try renderToken(tree, ais, thread_local_token, Space.Space); // threadlocal2167 try renderToken(ais, tree, thread_local_token, Space.Space); // threadlocal
2263 }2168 }
2264 try renderToken(tree, ais, var_decl.mut_token, Space.Space); // var2169 try renderToken(ais, tree, var_decl.mut_token, Space.Space); // var
22652170
2266 const name_space = if (var_decl.getTypeNode() == null and2171 const name_space = if (var_decl.getTypeNode() == null and
2267 (var_decl.getAlignNode() != null or2172 (var_decl.getAlignNode() != null or
...@@ -2270,10 +2175,10 @@ fn renderVarDecl(...@@ -2270,10 +2175,10 @@ fn renderVarDecl(
2270 Space.Space2175 Space.Space
2271 else2176 else
2272 Space.None;2177 Space.None;
2273 try renderToken(tree, ais, var_decl.name_token, name_space);2178 try renderToken(ais, tree, var_decl.name_token, name_space);
22742179
2275 if (var_decl.getTypeNode()) |type_node| {2180 if (var_decl.getTypeNode()) |type_node| {
2276 try renderToken(tree, ais, tree.nextToken(var_decl.name_token), Space.Space);2181 try renderToken(ais, tree, tree.nextToken(var_decl.name_token), Space.Space);
2277 const s = if (var_decl.getAlignNode() != null or2182 const s = if (var_decl.getAlignNode() != null or
2278 var_decl.getSectionNode() != null or2183 var_decl.getSectionNode() != null or
2279 var_decl.getInitNode() != null) Space.Space else Space.None;2184 var_decl.getInitNode() != null) Space.Space else Space.None;
...@@ -2284,22 +2189,22 @@ fn renderVarDecl(...@@ -2284,22 +2189,22 @@ fn renderVarDecl(
2284 const lparen = tree.prevToken(align_node.firstToken());2189 const lparen = tree.prevToken(align_node.firstToken());
2285 const align_kw = tree.prevToken(lparen);2190 const align_kw = tree.prevToken(lparen);
2286 const rparen = tree.nextToken(align_node.lastToken());2191 const rparen = tree.nextToken(align_node.lastToken());
2287 try renderToken(tree, ais, align_kw, Space.None); // align2192 try renderToken(ais, tree, align_kw, Space.None); // align
2288 try renderToken(tree, ais, lparen, Space.None); // (2193 try renderToken(ais, tree, lparen, Space.None); // (
2289 try renderExpression(allocator, ais, tree, align_node, Space.None);2194 try renderExpression(allocator, ais, tree, align_node, Space.None);
2290 const s = if (var_decl.getSectionNode() != null or var_decl.getInitNode() != null) Space.Space else Space.None;2195 const s = if (var_decl.getSectionNode() != null or var_decl.getInitNode() != null) Space.Space else Space.None;
2291 try renderToken(tree, ais, rparen, s); // )2196 try renderToken(ais, tree, rparen, s); // )
2292 }2197 }
22932198
2294 if (var_decl.getSectionNode()) |section_node| {2199 if (var_decl.getSectionNode()) |section_node| {
2295 const lparen = tree.prevToken(section_node.firstToken());2200 const lparen = tree.prevToken(section_node.firstToken());
2296 const section_kw = tree.prevToken(lparen);2201 const section_kw = tree.prevToken(lparen);
2297 const rparen = tree.nextToken(section_node.lastToken());2202 const rparen = tree.nextToken(section_node.lastToken());
2298 try renderToken(tree, ais, section_kw, Space.None); // linksection2203 try renderToken(ais, tree, section_kw, Space.None); // linksection
2299 try renderToken(tree, ais, lparen, Space.None); // (2204 try renderToken(ais, tree, lparen, Space.None); // (
2300 try renderExpression(allocator, ais, tree, section_node, Space.None);2205 try renderExpression(allocator, ais, tree, section_node, Space.None);
2301 const s = if (var_decl.getInitNode() != null) Space.Space else Space.None;2206 const s = if (var_decl.getInitNode() != null) Space.Space else Space.None;
2302 try renderToken(tree, ais, rparen, s); // )2207 try renderToken(ais, tree, rparen, s); // )
2303 }2208 }
23042209
2305 if (var_decl.getInitNode()) |init_node| {2210 if (var_decl.getInitNode()) |init_node| {
...@@ -2312,268 +2217,150 @@ fn renderVarDecl(...@@ -2312,268 +2217,150 @@ fn renderVarDecl(
2312 {2217 {
2313 ais.pushIndent();2218 ais.pushIndent();
2314 defer ais.popIndent();2219 defer ais.popIndent();
2315 try renderToken(tree, ais, eq_token, eq_space); // =2220 try renderToken(ais, tree, eq_token, eq_space); // =
2316 }2221 }
2317 ais.pushIndentOneShot();2222 ais.pushIndentOneShot();
2318 try renderExpression(allocator, ais, tree, init_node, Space.None);2223 try renderExpression(allocator, ais, tree, init_node, Space.None);
2319 }2224 }
23202225
2321 try renderToken(tree, ais, var_decl.semicolon_token, Space.Newline);2226 try renderToken(ais, tree, var_decl.semicolon_token, Space.Newline);
2322}2227}
23232228
2324fn renderParamDecl(2229fn renderParamDecl(
2325 allocator: *mem.Allocator,2230 allocator: *mem.Allocator,
2326 ais: anytype,2231 ais: *Ais,
2327 tree: *ast.Tree,2232 tree: ast.Tree,
2328 param_decl: ast.Node.FnProto.ParamDecl,2233 param_decl: ast.Node.FnProto.ParamDecl,
2329 space: Space,2234 space: Space,
2330) (@TypeOf(ais.*).Error || Error)!void {2235) Error!void {
2331 try renderDocComments(tree, ais, param_decl, param_decl.doc_comments);2236 try renderDocComments(tree, ais, param_decl, param_decl.doc_comments);
23322237
2333 if (param_decl.comptime_token) |comptime_token| {2238 if (param_decl.comptime_token) |comptime_token| {
2334 try renderToken(tree, ais, comptime_token, Space.Space);2239 try renderToken(ais, tree, comptime_token, Space.Space);
2335 }2240 }
2336 if (param_decl.noalias_token) |noalias_token| {2241 if (param_decl.noalias_token) |noalias_token| {
2337 try renderToken(tree, ais, noalias_token, Space.Space);2242 try renderToken(ais, tree, noalias_token, Space.Space);
2338 }2243 }
2339 if (param_decl.name_token) |name_token| {2244 if (param_decl.name_token) |name_token| {
2340 try renderToken(tree, ais, name_token, Space.None);2245 try renderToken(ais, tree, name_token, Space.None);
2341 try renderToken(tree, ais, tree.nextToken(name_token), Space.Space); // :2246 try renderToken(ais, tree, tree.nextToken(name_token), Space.Space); // :
2342 }2247 }
2343 switch (param_decl.param_type) {2248 switch (param_decl.param_type) {
2344 .any_type, .type_expr => |node| try renderExpression(allocator, ais, tree, node, space),2249 .any_type, .type_expr => |node| try renderExpression(allocator, ais, tree, node, space),
2345 }2250 }
2346}2251}
23472252
2348fn renderStatement(2253fn renderStatement(ais: *Ais, tree: ast.Tree, base: ast.Node.Index) Error!void {
2349 allocator: *mem.Allocator,2254 @panic("TODO render statement");
2350 ais: anytype,2255 //switch (base.tag) {
2351 tree: *ast.Tree,2256 // .VarDecl => {
2352 base: *ast.Node,2257 // const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
2353) (@TypeOf(ais.*).Error || Error)!void {2258 // try renderVarDecl(allocator, ais, tree, var_decl);
2354 switch (base.tag) {2259 // },
2355 .VarDecl => {2260 // else => {
2356 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);2261 // if (base.requireSemiColon()) {
2357 try renderVarDecl(allocator, ais, tree, var_decl);2262 // try renderExpression(allocator, ais, tree, base, Space.None);
2358 },2263
2359 else => {2264 // const semicolon_index = tree.nextToken(base.lastToken());
2360 if (base.requireSemiColon()) {2265 // assert(tree.token_tags[semicolon_index] == .Semicolon);
2361 try renderExpression(allocator, ais, tree, base, Space.None);2266 // try renderToken(ais, tree, semicolon_index, Space.Newline);
23622267 // } else {
2363 const semicolon_index = tree.nextToken(base.lastToken());2268 // try renderExpression(allocator, ais, tree, base, Space.Newline);
2364 assert(tree.token_ids[semicolon_index] == .Semicolon);2269 // }
2365 try renderToken(tree, ais, semicolon_index, Space.Newline);2270 // },
2366 } else {2271 //}
2367 try renderExpression(allocator, ais, tree, base, Space.Newline);
2368 }
2369 },
2370 }
2371}2272}
23722273
2373const Space = enum {2274const Space = enum {
2374 None,2275 None,
2375 Newline,2276 Newline,
2277 /// `renderToken` will additionally consume the next token if it is a comma.
2376 Comma,2278 Comma,
2377 Space,2279 Space,
2378 SpaceOrOutdent,2280 SpaceOrOutdent,
2379 NoNewline,2281 NoNewline,
2282 /// Skips writing the possible line comment after the token.
2380 NoComment,2283 NoComment,
2381 BlockStart,2284 BlockStart,
2382};2285};
23832286
2384fn renderTokenOffset(2287fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Space) Error!void {
2385 tree: *ast.Tree,
2386 ais: anytype,
2387 token_index: ast.TokenIndex,
2388 space: Space,
2389 token_skip_bytes: usize,
2390) (@TypeOf(ais.*).Error || Error)!void {
2391 if (space == Space.BlockStart) {2288 if (space == Space.BlockStart) {
2392 // If placing the lbrace on the current line would cause an uggly gap then put the lbrace on the next line2289 // If placing the lbrace on the current line would cause an ugly gap then put the lbrace on the next line.
2393 const new_space = if (ais.isLineOverIndented()) Space.Newline else Space.Space;2290 const new_space = if (ais.isLineOverIndented()) Space.Newline else Space.Space;
2394 return renderToken(tree, ais, token_index, new_space);2291 return renderToken(ais, tree, token_index, new_space);
2395 }2292 }
23962293
2397 var token_loc = tree.token_locs[token_index];2294 const token_tags = tree.tokens.items(.tag);
2398 try ais.writer().writeAll(mem.trimRight(u8, tree.tokenSliceLoc(token_loc)[token_skip_bytes..], " "));2295 const token_starts = tree.tokens.items(.start);
23992296
2400 if (space == Space.NoComment)2297 const token_start = token_starts[token_index];
2401 return;2298 const token_tag = token_tags[token_index];
2299 const lexeme = token_tag.lexeme() orelse lexeme: {
2300 var tokenizer: std.zig.Tokenizer = .{
2301 .buffer = tree.source,
2302 .index = token_start,
2303 .pending_invalid_token = null,
2304 };
2305 const token = tokenizer.next();
2306 assert(token.tag == token_tag);
2307 break :lexeme tree.source[token.loc.start..token.loc.end];
2308 };
2309 try ais.writer().writeAll(lexeme);
24022310
2403 var next_token_id = tree.token_ids[token_index + 1];2311 switch (space) {
2404 var next_token_loc = tree.token_locs[token_index + 1];2312 .NoComment => {},
2313 .NoNewline => {},
2314 .None => {},
2315 .Comma => {
2316 const count = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], ", ");
2317 if (count == 0 and token_tags[token_index + 1] == .Comma) {
2318 return renderToken(ais, tree, token_index + 1, Space.Newline);
2319 }
2320 try ais.writer().writeAll(",");
24052321
2406 if (space == Space.Comma) switch (next_token_id) {2322 if (token_tags[token_index + 2] != .MultilineStringLiteralLine) {
2407 .Comma => return renderToken(tree, ais, token_index + 1, Space.Newline),
2408 .LineComment => {
2409 try ais.writer().writeAll(", ");
2410 return renderToken(tree, ais, token_index + 1, Space.Newline);
2411 },
2412 else => {
2413 if (token_index + 2 < tree.token_ids.len and
2414 tree.token_ids[token_index + 2] == .MultilineStringLiteralLine)
2415 {
2416 try ais.writer().writeAll(",");
2417 return;
2418 } else {
2419 try ais.writer().writeAll(",");
2420 try ais.insertNewline();2323 try ais.insertNewline();
2421 return;
2422 }2324 }
2423 },2325 },
2424 };2326 .SpaceOrOutdent => @panic("what does this even do"),
24252327 .Space => {
2426 // Skip over same line doc comments2328 _ = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1], "");
2427 var offset: usize = 1;
2428 if (next_token_id == .DocComment) {
2429 const loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
2430 if (loc.line == 0) {
2431 offset += 1;
2432 next_token_id = tree.token_ids[token_index + offset];
2433 next_token_loc = tree.token_locs[token_index + offset];
2434 }
2435 }
2436
2437 if (next_token_id != .LineComment) {
2438 switch (space) {
2439 Space.None, Space.NoNewline => return,
2440 Space.Newline => {
2441 if (next_token_id == .MultilineStringLiteralLine) {
2442 return;
2443 } else {
2444 try ais.insertNewline();
2445 return;
2446 }
2447 },
2448 Space.Space, Space.SpaceOrOutdent => {
2449 if (next_token_id == .MultilineStringLiteralLine)
2450 return;
2451 try ais.writer().writeByte(' ');
2452 return;
2453 },
2454 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
2455 }
2456 }
2457
2458 while (true) {
2459 const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(next_token_loc), " ").len == 2;
2460 if (comment_is_empty) {
2461 switch (space) {
2462 Space.Newline => {
2463 offset += 1;
2464 token_loc = next_token_loc;
2465 next_token_id = tree.token_ids[token_index + offset];
2466 next_token_loc = tree.token_locs[token_index + offset];
2467 if (next_token_id != .LineComment) {
2468 try ais.insertNewline();
2469 return;
2470 }
2471 },
2472 else => break,
2473 }
2474 } else {
2475 break;
2476 }
2477 }
2478
2479 var loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
2480 if (loc.line == 0) {
2481 if (tree.token_ids[token_index] != .MultilineStringLiteralLine) {
2482 try ais.writer().writeByte(' ');2329 try ais.writer().writeByte(' ');
2483 }2330 },
2484 try ais.writer().writeAll(mem.trimRight(u8, tree.tokenSliceLoc(next_token_loc), " "));2331 .Newline => {
2485 offset = 2;2332 if (token_tags[token_index + 1] != .MultilineStringLiteralLine) {
2486 token_loc = next_token_loc;2333 try ais.insertNewline();
2487 next_token_loc = tree.token_locs[token_index + offset];
2488 next_token_id = tree.token_ids[token_index + offset];
2489 if (next_token_id != .LineComment) {
2490 switch (space) {
2491 .None, .Space, .SpaceOrOutdent => {
2492 try ais.insertNewline();
2493 },
2494 .Newline => {
2495 if (next_token_id == .MultilineStringLiteralLine) {
2496 return;
2497 } else {
2498 try ais.insertNewline();
2499 return;
2500 }
2501 },
2502 .NoNewline => {},
2503 .NoComment, .Comma, .BlockStart => unreachable,
2504 }
2505 return;
2506 }
2507 loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
2508 }
2509
2510 while (true) {
2511 // translate-c doesn't generate correct newlines
2512 // in generated code (loc.line == 0) so treat that case
2513 // as though there was meant to be a newline between the tokens
2514 var newline_count = if (loc.line <= 1) @as(u8, 1) else @as(u8, 2);
2515 while (newline_count > 0) : (newline_count -= 1) try ais.insertNewline();
2516 try ais.writer().writeAll(mem.trimRight(u8, tree.tokenSliceLoc(next_token_loc), " "));
2517
2518 offset += 1;
2519 token_loc = next_token_loc;
2520 next_token_loc = tree.token_locs[token_index + offset];
2521 next_token_id = tree.token_ids[token_index + offset];
2522 if (next_token_id != .LineComment) {
2523 switch (space) {
2524 .Newline => {
2525 if (next_token_id == .MultilineStringLiteralLine) {
2526 return;
2527 } else {
2528 try ais.insertNewline();
2529 return;
2530 }
2531 },
2532 .None, .Space, .SpaceOrOutdent => {
2533 try ais.insertNewline();
2534 },
2535 .NoNewline => {},
2536 .NoComment, .Comma, .BlockStart => unreachable,
2537 }2334 }
2538 return;2335 },
2539 }2336 .BlockStart => unreachable,
2540 loc = tree.tokenLocationLoc(token_loc.end, next_token_loc);
2541 }2337 }
2542}2338}
25432339
2544fn renderToken(
2545 tree: *ast.Tree,
2546 ais: anytype,
2547 token_index: ast.TokenIndex,
2548 space: Space,
2549) (@TypeOf(ais.*).Error || Error)!void {
2550 return renderTokenOffset(tree, ais, token_index, space, 0);
2551}
2552
2553fn renderDocComments(2340fn renderDocComments(
2554 tree: *ast.Tree,2341 tree: ast.Tree,
2555 ais: anytype,2342 ais: *Ais,
2556 node: anytype,2343 node: anytype,
2557 doc_comments: ?*ast.Node.DocComment,2344 doc_comments: ?ast.Node.Index.DocComment,
2558) (@TypeOf(ais.*).Error || Error)!void {2345) Error!void {
2559 const comment = doc_comments orelse return;2346 const comment = doc_comments orelse return;
2560 return renderDocCommentsToken(tree, ais, comment, node.firstToken());2347 return renderDocCommentsToken(tree, ais, comment, node.firstToken());
2561}2348}
25622349
2563fn renderDocCommentsToken(2350fn renderDocCommentsToken(
2564 tree: *ast.Tree,2351 tree: ast.Tree,
2565 ais: anytype,2352 ais: *Ais,
2566 comment: *ast.Node.DocComment,2353 comment: ast.Node.Index.DocComment,
2567 first_token: ast.TokenIndex,2354 first_token: ast.TokenIndex,
2568) (@TypeOf(ais.*).Error || Error)!void {2355) Error!void {
2569 var tok_i = comment.first_line;2356 var tok_i = comment.first_line;
2570 while (true) : (tok_i += 1) {2357 while (true) : (tok_i += 1) {
2571 switch (tree.token_ids[tok_i]) {2358 switch (tree.token_tags[tok_i]) {
2572 .DocComment, .ContainerDocComment => {2359 .DocComment, .ContainerDocComment => {
2573 if (comment.first_line < first_token) {2360 if (comment.first_line < first_token) {
2574 try renderToken(tree, ais, tok_i, Space.Newline);2361 try renderToken(ais, tree, tok_i, Space.Newline);
2575 } else {2362 } else {
2576 try renderToken(tree, ais, tok_i, Space.NoComment);2363 try renderToken(ais, tree, tok_i, Space.NoComment);
2577 try ais.insertNewline();2364 try ais.insertNewline();
2578 }2365 }
2579 },2366 },
...@@ -2596,7 +2383,7 @@ fn nodeIsBlock(base: *const ast.Node) bool {...@@ -2596,7 +2383,7 @@ fn nodeIsBlock(base: *const ast.Node) bool {
2596 };2383 };
2597}2384}
25982385
2599fn nodeCausesSliceOpSpace(base: *ast.Node) bool {2386fn nodeCausesSliceOpSpace(base: ast.Node.Index) bool {
2600 return switch (base.tag) {2387 return switch (base.tag) {
2601 .Catch,2388 .Catch,
2602 .Add,2389 .Add,
...@@ -2646,7 +2433,7 @@ fn nodeCausesSliceOpSpace(base: *ast.Node) bool {...@@ -2646,7 +2433,7 @@ fn nodeCausesSliceOpSpace(base: *ast.Node) bool {
2646 };2433 };
2647}2434}
26482435
2649fn copyFixingWhitespace(ais: anytype, slice: []const u8) @TypeOf(ais.*).Error!void {2436fn copyFixingWhitespace(ais: *Ais, slice: []const u8) @TypeOf(ais.*).Error!void {
2650 for (slice) |byte| switch (byte) {2437 for (slice) |byte| switch (byte) {
2651 '\t' => try ais.writer().writeAll(" "),2438 '\t' => try ais.writer().writeAll(" "),
2652 '\r' => {},2439 '\r' => {},
...@@ -2656,12 +2443,12 @@ fn copyFixingWhitespace(ais: anytype, slice: []const u8) @TypeOf(ais.*).Error!vo...@@ -2656,12 +2443,12 @@ fn copyFixingWhitespace(ais: anytype, slice: []const u8) @TypeOf(ais.*).Error!vo
26562443
2657// Returns the number of nodes in `expr` that are on the same line as `rtoken`,2444// Returns the number of nodes in `expr` that are on the same line as `rtoken`,
2658// or null if they all are on the same line.2445// or null if they all are on the same line.
2659fn rowSize(tree: *ast.Tree, exprs: []*ast.Node, rtoken: ast.TokenIndex) ?usize {2446fn rowSize(tree: ast.Tree, exprs: []ast.Node.Index, rtoken: ast.TokenIndex) ?usize {
2660 const first_token = exprs[0].firstToken();2447 const first_token = exprs[0].firstToken();
2661 const first_loc = tree.tokenLocation(tree.token_locs[first_token].start, rtoken);2448 const first_loc = tree.tokenLocation(tree.token_locs[first_token].start, rtoken);
2662 if (first_loc.line == 0) {2449 if (first_loc.line == 0) {
2663 const maybe_comma = tree.prevToken(rtoken);2450 const maybe_comma = tree.prevToken(rtoken);
2664 if (tree.token_ids[maybe_comma] == .Comma)2451 if (tree.token_tags[maybe_comma] == .Comma)
2665 return 1;2452 return 1;
2666 return null; // no newlines2453 return null; // no newlines
2667 }2454 }
lib/std/zig/tokenizer.zig+18-13
...@@ -195,22 +195,23 @@ pub const Token = struct {...@@ -195,22 +195,23 @@ pub const Token = struct {
195 Keyword_volatile,195 Keyword_volatile,
196 Keyword_while,196 Keyword_while,
197197
198 pub fn symbol(tag: Tag) []const u8 {198 pub fn lexeme(tag: Tag) ?[]const u8 {
199 return switch (tag) {199 return switch (tag) {
200 .Invalid => "Invalid",200 .Invalid,
201 .Identifier,
202 .StringLiteral,
203 .MultilineStringLiteralLine,
204 .CharLiteral,
205 .Eof,
206 .Builtin,
207 .IntegerLiteral,
208 .FloatLiteral,
209 .DocComment,
210 .ContainerDocComment,
211 => null,
212
201 .Invalid_ampersands => "&&",213 .Invalid_ampersands => "&&",
202 .Invalid_periodasterisks => ".**",214 .Invalid_periodasterisks => ".**",
203 .Identifier => "Identifier",
204 .StringLiteral => "StringLiteral",
205 .MultilineStringLiteralLine => "MultilineStringLiteralLine",
206 .CharLiteral => "CharLiteral",
207 .Eof => "Eof",
208 .Builtin => "Builtin",
209 .IntegerLiteral => "IntegerLiteral",
210 .FloatLiteral => "FloatLiteral",
211 .DocComment => "DocComment",
212 .ContainerDocComment => "ContainerDocComment",
213
214 .Bang => "!",215 .Bang => "!",
215 .Pipe => "|",216 .Pipe => "|",
216 .PipePipe => "||",217 .PipePipe => "||",
...@@ -319,6 +320,10 @@ pub const Token = struct {...@@ -319,6 +320,10 @@ pub const Token = struct {
319 .Keyword_while => "while",320 .Keyword_while => "while",
320 };321 };
321 }322 }
323
324 pub fn symbol(tag: Tag) []const u8 {
325 return tag.lexeme() orelse @tagName(tag);
326 }
322 };327 };
323};328};
324329