commit 885581323ca2f78fde42a1d6a10b44f047a5a69a (tree)
parent 80f4342dd1e6b5f62be418d6bc917897d6433edf
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Wed, 11 Feb 2026 06:11:57 +0000
reorder tests better
Diffstat:
| M | README.md | | | 6 | +----- |
| M | parser_test.zig | | | 4372 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
2 files changed, 2188 insertions(+), 2190 deletions(-)
diff --git a/README.md b/README.md
@@ -4,11 +4,7 @@ zig0 aspires to be an interpreter of zig 0.15.1 written in C.
Quick test:
- zig build
-
-If it complains about formatting, here is a mutable command that will fix it:
-
- zig build fmt
+ zig build fmt && zig build
# Debugging tips
diff --git a/parser_test.zig b/parser_test.zig
@@ -1,550 +1,8 @@
const std = @import("std");
-const testing = std.testing;
-
-const Ast = std.zig.Ast;
-const Allocator = std.mem.Allocator;
-
-const c = @cImport({
- @cInclude("ast.h");
-});
-
-const zigToken = @import("./tokenizer_test.zig").zigToken;
-
-fn zigNode(token: c_uint) Ast.Node.Tag {
- return switch (token) {
- c.AST_NODE_ROOT => .root,
- c.AST_NODE_TEST_DECL => .test_decl,
- c.AST_NODE_GLOBAL_VAR_DECL => .global_var_decl,
- c.AST_NODE_LOCAL_VAR_DECL => .local_var_decl,
- c.AST_NODE_SIMPLE_VAR_DECL => .simple_var_decl,
- c.AST_NODE_ALIGNED_VAR_DECL => .aligned_var_decl,
- c.AST_NODE_ERRDEFER => .@"errdefer",
- c.AST_NODE_DEFER => .@"defer",
- c.AST_NODE_CATCH => .@"catch",
- c.AST_NODE_FIELD_ACCESS => .field_access,
- c.AST_NODE_UNWRAP_OPTIONAL => .unwrap_optional,
- c.AST_NODE_EQUAL_EQUAL => .equal_equal,
- c.AST_NODE_BANG_EQUAL => .bang_equal,
- c.AST_NODE_LESS_THAN => .less_than,
- c.AST_NODE_GREATER_THAN => .greater_than,
- c.AST_NODE_LESS_OR_EQUAL => .less_or_equal,
- c.AST_NODE_GREATER_OR_EQUAL => .greater_or_equal,
- c.AST_NODE_ASSIGN_MUL => .assign_mul,
- c.AST_NODE_ASSIGN_DIV => .assign_div,
- c.AST_NODE_ASSIGN_MOD => .assign_mod,
- c.AST_NODE_ASSIGN_ADD => .assign_add,
- c.AST_NODE_ASSIGN_SUB => .assign_sub,
- c.AST_NODE_ASSIGN_SHL => .assign_shl,
- c.AST_NODE_ASSIGN_SHL_SAT => .assign_shl_sat,
- c.AST_NODE_ASSIGN_SHR => .assign_shr,
- c.AST_NODE_ASSIGN_BIT_AND => .assign_bit_and,
- c.AST_NODE_ASSIGN_BIT_XOR => .assign_bit_xor,
- c.AST_NODE_ASSIGN_BIT_OR => .assign_bit_or,
- c.AST_NODE_ASSIGN_MUL_WRAP => .assign_mul_wrap,
- c.AST_NODE_ASSIGN_ADD_WRAP => .assign_add_wrap,
- c.AST_NODE_ASSIGN_SUB_WRAP => .assign_sub_wrap,
- c.AST_NODE_ASSIGN_MUL_SAT => .assign_mul_sat,
- c.AST_NODE_ASSIGN_ADD_SAT => .assign_add_sat,
- c.AST_NODE_ASSIGN_SUB_SAT => .assign_sub_sat,
- c.AST_NODE_ASSIGN => .assign,
- c.AST_NODE_ASSIGN_DESTRUCTURE => .assign_destructure,
- c.AST_NODE_MERGE_ERROR_SETS => .merge_error_sets,
- c.AST_NODE_MUL => .mul,
- c.AST_NODE_DIV => .div,
- c.AST_NODE_MOD => .mod,
- c.AST_NODE_ARRAY_MULT => .array_mult,
- c.AST_NODE_MUL_WRAP => .mul_wrap,
- c.AST_NODE_MUL_SAT => .mul_sat,
- c.AST_NODE_ADD => .add,
- c.AST_NODE_SUB => .sub,
- c.AST_NODE_ARRAY_CAT => .array_cat,
- c.AST_NODE_ADD_WRAP => .add_wrap,
- c.AST_NODE_SUB_WRAP => .sub_wrap,
- c.AST_NODE_ADD_SAT => .add_sat,
- c.AST_NODE_SUB_SAT => .sub_sat,
- c.AST_NODE_SHL => .shl,
- c.AST_NODE_SHL_SAT => .shl_sat,
- c.AST_NODE_SHR => .shr,
- c.AST_NODE_BIT_AND => .bit_and,
- c.AST_NODE_BIT_XOR => .bit_xor,
- c.AST_NODE_BIT_OR => .bit_or,
- c.AST_NODE_ORELSE => .@"orelse",
- c.AST_NODE_BOOL_AND => .bool_and,
- c.AST_NODE_BOOL_OR => .bool_or,
- c.AST_NODE_BOOL_NOT => .bool_not,
- c.AST_NODE_NEGATION => .negation,
- c.AST_NODE_BIT_NOT => .bit_not,
- c.AST_NODE_NEGATION_WRAP => .negation_wrap,
- c.AST_NODE_ADDRESS_OF => .address_of,
- c.AST_NODE_TRY => .@"try",
- c.AST_NODE_OPTIONAL_TYPE => .optional_type,
- c.AST_NODE_ARRAY_TYPE => .array_type,
- c.AST_NODE_ARRAY_TYPE_SENTINEL => .array_type_sentinel,
- c.AST_NODE_PTR_TYPE_ALIGNED => .ptr_type_aligned,
- c.AST_NODE_PTR_TYPE_SENTINEL => .ptr_type_sentinel,
- c.AST_NODE_PTR_TYPE => .ptr_type,
- c.AST_NODE_PTR_TYPE_BIT_RANGE => .ptr_type_bit_range,
- c.AST_NODE_SLICE_OPEN => .slice_open,
- c.AST_NODE_SLICE => .slice,
- c.AST_NODE_SLICE_SENTINEL => .slice_sentinel,
- c.AST_NODE_DEREF => .deref,
- c.AST_NODE_ARRAY_ACCESS => .array_access,
- c.AST_NODE_ARRAY_INIT_ONE => .array_init_one,
- c.AST_NODE_ARRAY_INIT_ONE_COMMA => .array_init_one_comma,
- c.AST_NODE_ARRAY_INIT_DOT_TWO => .array_init_dot_two,
- c.AST_NODE_ARRAY_INIT_DOT_TWO_COMMA => .array_init_dot_two_comma,
- c.AST_NODE_ARRAY_INIT_DOT => .array_init_dot,
- c.AST_NODE_ARRAY_INIT_DOT_COMMA => .array_init_dot_comma,
- c.AST_NODE_ARRAY_INIT => .array_init,
- c.AST_NODE_ARRAY_INIT_COMMA => .array_init_comma,
- c.AST_NODE_STRUCT_INIT_ONE => .struct_init_one,
- c.AST_NODE_STRUCT_INIT_ONE_COMMA => .struct_init_one_comma,
- c.AST_NODE_STRUCT_INIT_DOT_TWO => .struct_init_dot_two,
- c.AST_NODE_STRUCT_INIT_DOT_TWO_COMMA => .struct_init_dot_two_comma,
- c.AST_NODE_STRUCT_INIT_DOT => .struct_init_dot,
- c.AST_NODE_STRUCT_INIT_DOT_COMMA => .struct_init_dot_comma,
- c.AST_NODE_STRUCT_INIT => .struct_init,
- c.AST_NODE_STRUCT_INIT_COMMA => .struct_init_comma,
- c.AST_NODE_CALL_ONE => .call_one,
- c.AST_NODE_CALL_ONE_COMMA => .call_one_comma,
- c.AST_NODE_CALL => .call,
- c.AST_NODE_CALL_COMMA => .call_comma,
- c.AST_NODE_SWITCH => .@"switch",
- c.AST_NODE_SWITCH_COMMA => .switch_comma,
- c.AST_NODE_SWITCH_CASE_ONE => .switch_case_one,
- c.AST_NODE_SWITCH_CASE_INLINE_ONE => .switch_case_inline_one,
- c.AST_NODE_SWITCH_CASE => .switch_case,
- c.AST_NODE_SWITCH_CASE_INLINE => .switch_case_inline,
- c.AST_NODE_SWITCH_RANGE => .switch_range,
- c.AST_NODE_WHILE_SIMPLE => .while_simple,
- c.AST_NODE_WHILE_CONT => .while_cont,
- c.AST_NODE_WHILE => .@"while",
- c.AST_NODE_FOR_SIMPLE => .for_simple,
- c.AST_NODE_FOR => .@"for",
- c.AST_NODE_FOR_RANGE => .for_range,
- c.AST_NODE_IF_SIMPLE => .if_simple,
- c.AST_NODE_IF => .@"if",
- c.AST_NODE_SUSPEND => .@"suspend",
- c.AST_NODE_RESUME => .@"resume",
- c.AST_NODE_CONTINUE => .@"continue",
- c.AST_NODE_BREAK => .@"break",
- c.AST_NODE_RETURN => .@"return",
- c.AST_NODE_FN_PROTO_SIMPLE => .fn_proto_simple,
- c.AST_NODE_FN_PROTO_MULTI => .fn_proto_multi,
- c.AST_NODE_FN_PROTO_ONE => .fn_proto_one,
- c.AST_NODE_FN_PROTO => .fn_proto,
- c.AST_NODE_FN_DECL => .fn_decl,
- c.AST_NODE_ANYFRAME_TYPE => .anyframe_type,
- c.AST_NODE_ANYFRAME_LITERAL => .anyframe_literal,
- c.AST_NODE_CHAR_LITERAL => .char_literal,
- c.AST_NODE_NUMBER_LITERAL => .number_literal,
- c.AST_NODE_UNREACHABLE_LITERAL => .unreachable_literal,
- c.AST_NODE_IDENTIFIER => .identifier,
- c.AST_NODE_ENUM_LITERAL => .enum_literal,
- c.AST_NODE_STRING_LITERAL => .string_literal,
- c.AST_NODE_MULTILINE_STRING_LITERAL => .multiline_string_literal,
- c.AST_NODE_GROUPED_EXPRESSION => .grouped_expression,
- c.AST_NODE_BUILTIN_CALL_TWO => .builtin_call_two,
- c.AST_NODE_BUILTIN_CALL_TWO_COMMA => .builtin_call_two_comma,
- c.AST_NODE_BUILTIN_CALL => .builtin_call,
- c.AST_NODE_BUILTIN_CALL_COMMA => .builtin_call_comma,
- c.AST_NODE_ERROR_SET_DECL => .error_set_decl,
- c.AST_NODE_CONTAINER_DECL => .container_decl,
- c.AST_NODE_CONTAINER_DECL_TRAILING => .container_decl_trailing,
- c.AST_NODE_CONTAINER_DECL_TWO => .container_decl_two,
- c.AST_NODE_CONTAINER_DECL_TWO_TRAILING => .container_decl_two_trailing,
- c.AST_NODE_CONTAINER_DECL_ARG => .container_decl_arg,
- c.AST_NODE_CONTAINER_DECL_ARG_TRAILING => .container_decl_arg_trailing,
- c.AST_NODE_TAGGED_UNION => .tagged_union,
- c.AST_NODE_TAGGED_UNION_TRAILING => .tagged_union_trailing,
- c.AST_NODE_TAGGED_UNION_TWO => .tagged_union_two,
- c.AST_NODE_TAGGED_UNION_TWO_TRAILING => .tagged_union_two_trailing,
- c.AST_NODE_TAGGED_UNION_ENUM_TAG => .tagged_union_enum_tag,
- c.AST_NODE_TAGGED_UNION_ENUM_TAG_TRAILING => .tagged_union_enum_tag_trailing,
- c.AST_NODE_CONTAINER_FIELD_INIT => .container_field_init,
- c.AST_NODE_CONTAINER_FIELD_ALIGN => .container_field_align,
- c.AST_NODE_CONTAINER_FIELD => .container_field,
- c.AST_NODE_COMPTIME => .@"comptime",
- c.AST_NODE_NOSUSPEND => .@"nosuspend",
- c.AST_NODE_BLOCK_TWO => .block_two,
- c.AST_NODE_BLOCK_TWO_SEMICOLON => .block_two_semicolon,
- c.AST_NODE_BLOCK => .block,
- c.AST_NODE_BLOCK_SEMICOLON => .block_semicolon,
- c.AST_NODE_ASM_SIMPLE => .asm_simple,
- c.AST_NODE_ASM_LEGACY => .asm_legacy,
- c.AST_NODE_ASM => .@"asm",
- c.AST_NODE_ASM_OUTPUT => .asm_output,
- c.AST_NODE_ASM_INPUT => .asm_input,
- c.AST_NODE_ERROR_VALUE => .error_value,
- c.AST_NODE_ERROR_UNION => .error_union,
- else => undefined,
- };
-}
-
-fn toIndex(v: u32) Ast.Node.Index {
- return @enumFromInt(v);
-}
-
-fn toOptIndex(v: u32) Ast.Node.OptionalIndex {
- return if (v == 0) .none else @enumFromInt(v);
-}
-
-fn toExtraIndex(v: u32) Ast.ExtraIndex {
- return @enumFromInt(v);
-}
-
-fn toOptTokenIndex(v: u32) Ast.OptionalTokenIndex {
- return @enumFromInt(v);
-}
-
-fn zigData(tag: Ast.Node.Tag, lhs: u32, rhs: u32) Ast.Node.Data {
- return switch (tag) {
- // data unused
- .identifier,
- .string_literal,
- .char_literal,
- .number_literal,
- .unreachable_literal,
- .anyframe_literal,
- .enum_literal,
- .error_value,
- => .{ .opt_node_and_opt_node = .{ toOptIndex(lhs), toOptIndex(rhs) } },
-
- // .node (single node index)
- .@"defer",
- .@"comptime",
- .@"nosuspend",
- .@"suspend",
- .@"resume",
- .bool_not,
- .negation,
- .bit_not,
- .negation_wrap,
- .address_of,
- .@"try",
- .deref,
- .optional_type,
- => .{ .node = toIndex(lhs) },
-
- // .opt_node (single optional node)
- .@"return",
- => .{ .opt_node = toOptIndex(lhs) },
-
- // .node_and_node
- .fn_decl,
- .container_field_align,
- .error_union,
- .@"catch",
- .equal_equal,
- .bang_equal,
- .less_than,
- .greater_than,
- .less_or_equal,
- .greater_or_equal,
- .assign_mul,
- .assign_div,
- .assign_mod,
- .assign_add,
- .assign_sub,
- .assign_shl,
- .assign_shl_sat,
- .assign_shr,
- .assign_bit_and,
- .assign_bit_xor,
- .assign_bit_or,
- .assign_mul_wrap,
- .assign_add_wrap,
- .assign_sub_wrap,
- .assign_mul_sat,
- .assign_add_sat,
- .assign_sub_sat,
- .assign,
- .merge_error_sets,
- .mul,
- .div,
- .mod,
- .array_mult,
- .mul_wrap,
- .mul_sat,
- .add,
- .sub,
- .array_cat,
- .add_wrap,
- .sub_wrap,
- .add_sat,
- .sub_sat,
- .shl,
- .shl_sat,
- .shr,
- .bit_and,
- .bit_xor,
- .bit_or,
- .@"orelse",
- .bool_and,
- .bool_or,
- .array_type,
- .array_access,
- .switch_range,
- => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
-
- // .opt_node_and_opt_node
- .fn_proto_simple,
- .simple_var_decl,
- .block_two,
- .block_two_semicolon,
- .builtin_call_two,
- .builtin_call_two_comma,
- .container_decl_two,
- .container_decl_two_trailing,
- .tagged_union_two,
- .tagged_union_two_trailing,
- .struct_init_dot_two,
- .struct_init_dot_two_comma,
- .array_init_dot_two,
- .array_init_dot_two_comma,
- => .{ .opt_node_and_opt_node = .{ toOptIndex(lhs), toOptIndex(rhs) } },
-
- // .node_and_opt_node
- .call_one,
- .call_one_comma,
- .struct_init_one,
- .struct_init_one_comma,
- .container_field_init,
- .aligned_var_decl,
- => .{ .node_and_opt_node = .{ toIndex(lhs), toOptIndex(rhs) } },
-
- // .node_and_node (array_init_one uses node_and_node, not
- // node_and_opt_node)
- .array_init_one,
- .array_init_one_comma,
- => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
-
- // .opt_node_and_node
- .ptr_type_aligned,
- .ptr_type_sentinel,
- .switch_case_one,
- .switch_case_inline_one,
- => .{ .opt_node_and_node = .{ toOptIndex(lhs), toIndex(rhs) } },
-
- // .node_and_extra
- .call,
- .call_comma,
- .container_field,
- .array_type_sentinel,
- .slice,
- .slice_sentinel,
- .array_init,
- .array_init_comma,
- .struct_init,
- .struct_init_comma,
- .@"switch",
- .switch_comma,
- .container_decl_arg,
- .container_decl_arg_trailing,
- .tagged_union_enum_tag,
- .tagged_union_enum_tag_trailing,
- .@"asm",
- => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
-
- // .extra_and_node
- .assign_destructure,
- .switch_case,
- .switch_case_inline,
- .ptr_type,
- .ptr_type_bit_range,
- => .{ .extra_and_node = .{ toExtraIndex(lhs), toIndex(rhs) } },
-
- // .extra_and_opt_node
- .global_var_decl,
- .local_var_decl,
- .fn_proto_multi,
- .fn_proto_one,
- .fn_proto,
- => .{ .extra_and_opt_node = .{ toExtraIndex(lhs), toOptIndex(rhs) } },
-
- // .extra_range (SubRange)
- .root,
- .block,
- .block_semicolon,
- .builtin_call,
- .builtin_call_comma,
- .container_decl,
- .container_decl_trailing,
- .tagged_union,
- .tagged_union_trailing,
- .array_init_dot,
- .array_init_dot_comma,
- .struct_init_dot,
- .struct_init_dot_comma,
- => .{ .extra_range = .{ .start = toExtraIndex(lhs), .end = toExtraIndex(rhs) } },
-
- // .node_and_token
- .grouped_expression,
- .asm_input,
- .asm_simple,
- .field_access,
- .unwrap_optional,
- => .{ .node_and_token = .{ toIndex(lhs), rhs } },
-
- // .opt_node_and_token
- .asm_output,
- => .{ .opt_node_and_token = .{ toOptIndex(lhs), rhs } },
-
- // .opt_token_and_node
- .test_decl,
- .@"errdefer",
- => .{ .opt_token_and_node = .{ toOptTokenIndex(lhs), toIndex(rhs) } },
-
- // .opt_token_and_opt_node
- .@"break",
- .@"continue",
- => .{ .opt_token_and_opt_node = .{ toOptTokenIndex(lhs), toOptIndex(rhs) } },
-
- // .token_and_token
- .error_set_decl,
- .multiline_string_literal,
- => .{ .token_and_token = .{ lhs, rhs } },
-
- // .token_and_node
- .anyframe_type,
- => .{ .token_and_node = .{ lhs, toIndex(rhs) } },
-
- // .node_and_node for slice_open (lhs[rhs..])
- .slice_open,
- => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
-
- .while_simple,
- .for_simple,
- .if_simple,
- => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
-
- .while_cont,
- .@"while",
- .@"if",
- => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
-
- .for_range,
- => .{ .node_and_opt_node = .{ toIndex(lhs), toOptIndex(rhs) } },
-
- .@"for",
- => .{ .@"for" = .{ toExtraIndex(lhs), @bitCast(rhs) } },
-
- .asm_legacy,
- => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
- };
-}
-
-// zigAst converts a c.Ast to std.Zig.Ast. The resulting Ast should be freed with deinit().
-fn zigAst(gpa: Allocator, c_ast: c.Ast) !Ast {
- var tokens = Ast.TokenList{};
- try tokens.resize(gpa, c_ast.tokens.len);
- errdefer tokens.deinit(gpa);
-
- for (0..c_ast.tokens.len) |i|
- tokens.set(i, .{
- .tag = zigToken(c_ast.tokens.tags[i]),
- .start = c_ast.tokens.starts[i],
- });
-
- var nodes = Ast.NodeList{};
- try nodes.resize(gpa, c_ast.nodes.len);
- errdefer nodes.deinit(gpa);
-
- for (0..c_ast.nodes.len) |i| {
- const tag = zigNode(c_ast.nodes.tags[i]);
- nodes.set(i, .{
- .tag = tag,
- .main_token = c_ast.nodes.main_tokens[i],
- .data = zigData(tag, c_ast.nodes.datas[i].lhs, c_ast.nodes.datas[i].rhs),
- });
- }
-
- const extra_data = try gpa.alloc(u32, c_ast.extra_data.len);
- errdefer gpa.free(extra_data);
- @memcpy(extra_data, c_ast.extra_data.arr[0..c_ast.extra_data.len]);
-
- // creating a dummy `errors` slice, so deinit can free it.
- const errors = try gpa.alloc(Ast.Error, 0);
- errdefer gpa.free(errors);
-
- return Ast{
- .source = c_ast.source[0..c_ast.source_len :0],
- .mode = .zig,
- .tokens = tokens.slice(),
- .nodes = nodes.slice(),
- .extra_data = extra_data,
- .errors = errors,
- };
-}
-
-
-// copy-past from parser_test.zig
-const mem = std.mem;
-const print = std.debug.print;
-const io = std.io;
-const maxInt = std.math.maxInt;
-
-var fixed_buffer_mem: [100 * 1024]u8 = undefined;
-
-fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
- var stderr_buf: [4096]u8 = undefined;
- var stderr_file_writer = std.fs.File.stderr().writer(&stderr_buf);
- const stderr = &stderr_file_writer.interface;
-
- //var tree = try std.zig.Ast.parse(allocator, source, .zig);
- var c_tree = c.astParse(source, @intCast(source.len));
- defer c.astDeinit(&c_tree);
- var tree = try zigAst(allocator, c_tree);
- defer tree.deinit(allocator);
-
- for (tree.errors) |parse_error| {
- const loc = tree.tokenLocation(0, parse_error.token);
- try stderr.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 });
- try tree.renderError(parse_error, stderr);
- try stderr.print("\n{s}\n", .{source[loc.line_start..loc.line_end]});
- {
- var i: usize = 0;
- while (i < loc.column) : (i += 1) {
- try stderr.writeAll(" ");
- }
- try stderr.writeAll("^");
- }
- try stderr.writeAll("\n");
- }
- if (tree.errors.len != 0) {
- return error.ParseError;
- }
-
- const formatted = try tree.renderAlloc(allocator);
- anything_changed.* = !mem.eql(u8, formatted, source);
- return formatted;
-}
-fn testTransformImpl(allocator: mem.Allocator, fba: *std.heap.FixedBufferAllocator, source: [:0]const u8, expected_source: []const u8) !void {
- // reset the fixed buffer allocator each run so that it can be re-used for each
- // iteration of the failing index
- fba.reset();
- var anything_changed: bool = undefined;
- const result_source = try testParse(source, allocator, &anything_changed);
- try std.testing.expectEqualStrings(expected_source, result_source);
- const changes_expected = source.ptr != expected_source.ptr;
- if (anything_changed != changes_expected) {
- print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected });
- return error.TestFailed;
- }
- try std.testing.expect(anything_changed == changes_expected);
- allocator.free(result_source);
-}
-fn testTransform(source: [:0]const u8, expected_source: []const u8) !void {
- var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
- return std.testing.checkAllAllocationFailures(fixed_allocator.allocator(), testTransformImpl, .{ &fixed_allocator, source, expected_source });
-}
-fn testCanonical(source: [:0]const u8) !void {
- return testTransform(source, source);
-}
-
-
-
-
+const mem = std.mem;
+const print = std.debug.print;
+const io = std.io;
+const maxInt = std.math.maxInt;
test "zig fmt: remove extra whitespace at start and end of file with comment between" {
try testTransform(
@@ -807,6 +265,13 @@ test "zig fmt: top-level tuple function call type" {
);
}
+test "zig fmt: top-level enum missing 'const name ='" {
+ try testError(
+ \\enum(u32)
+ \\
+ , &[_]Error{.expected_token});
+}
+
test "zig fmt: top-level for/while loop" {
try testCanonical(
\\for (foo) |_| foo
@@ -3405,2126 +2870,2663 @@ test "zig fmt: precedence" {
);
}
-test "zig fmt: prefix operators" {
+test "zig fmt: prefix operators" {
+ try testCanonical(
+ \\test "prefix operators" {
+ \\ try return --%~!&0;
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: call expression" {
+ try testCanonical(
+ \\test "test calls" {
+ \\ a();
+ \\ a(1);
+ \\ a(1, 2);
+ \\ a(1, 2) + a(1, 2);
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: anytype type" {
+ try testCanonical(
+ \\fn print(args: anytype) @This() {}
+ \\
+ );
+}
+
+test "zig fmt: functions" {
+ try testCanonical(
+ \\extern fn puts(s: *const u8) c_int;
+ \\extern "c" fn puts(s: *const u8) c_int;
+ \\export fn puts(s: *const u8) c_int;
+ \\inline fn puts(s: *const u8) c_int;
+ \\noinline fn puts(s: *const u8) c_int;
+ \\pub extern fn puts(s: *const u8) c_int;
+ \\pub extern "c" fn puts(s: *const u8) c_int;
+ \\pub export fn puts(s: *const u8) c_int;
+ \\pub inline fn puts(s: *const u8) c_int;
+ \\pub noinline fn puts(s: *const u8) c_int;
+ \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
+ \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
+ \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
+ \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
+ \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
+ \\pub fn callInlineFn(func: fn () callconv(.@"inline") void) void {
+ \\ func();
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: multiline string" {
+ try testCanonical(
+ \\test "" {
+ \\ const s1 =
+ \\ \\one
+ \\ \\two)
+ \\ \\three
+ \\ ;
+ \\ const s3 = // hi
+ \\ \\one
+ \\ \\two)
+ \\ \\three
+ \\ ;
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: multiline string with CRLF line endings" {
+ try testTransform("" ++
+ "const s =\r\n" ++
+ " \\\\one\r\n" ++
+ " \\\\two)\r\n" ++
+ " \\\\three\r\n" ++
+ ";\r\n",
+ \\const s =
+ \\ \\one
+ \\ \\two)
+ \\ \\three
+ \\;
+ \\
+ );
+}
+
+test "zig fmt: values" {
+ try testCanonical(
+ \\test "values" {
+ \\ 1;
+ \\ 1.0;
+ \\ "string";
+ \\ 'c';
+ \\ true;
+ \\ false;
+ \\ null;
+ \\ undefined;
+ \\ anyerror;
+ \\ this;
+ \\ unreachable;
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: indexing" {
+ try testCanonical(
+ \\test "test index" {
+ \\ a[0];
+ \\ a[0 + 5];
+ \\ a[0..];
+ \\ a[0..5];
+ \\ a[a[0]];
+ \\ a[a[0..]];
+ \\ a[a[0..5]];
+ \\ a[a[0]..];
+ \\ a[a[0..5]..];
+ \\ a[a[0]..a[0]];
+ \\ a[a[0..5]..a[0]];
+ \\ a[a[0..5]..a[0..5]];
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: struct declaration" {
+ try testCanonical(
+ \\const S = struct {
+ \\ const Self = @This();
+ \\ f1: u8,
+ \\ f3: u8,
+ \\
+ \\ f2: u8,
+ \\
+ \\ fn method(self: *Self) Self {
+ \\ return self.*;
+ \\ }
+ \\};
+ \\
+ \\const Ps = packed struct {
+ \\ a: u8,
+ \\ b: u8,
+ \\
+ \\ c: u8,
+ \\};
+ \\
+ \\const Ps = packed struct(u32) {
+ \\ a: u1,
+ \\ b: u2,
+ \\
+ \\ c: u29,
+ \\};
+ \\
+ \\const Es = extern struct {
+ \\ a: u8,
+ \\ b: u8,
+ \\
+ \\ c: u8,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: enum declaration" {
+ try testCanonical(
+ \\const E = enum {
+ \\ Ok,
+ \\ SomethingElse = 0,
+ \\};
+ \\
+ \\const E2 = enum(u8) {
+ \\ Ok,
+ \\ SomethingElse = 255,
+ \\ SomethingThird,
+ \\};
+ \\
+ \\const Ee = extern enum {
+ \\ Ok,
+ \\ SomethingElse,
+ \\ SomethingThird,
+ \\};
+ \\
+ \\const Ep = packed enum {
+ \\ Ok,
+ \\ SomethingElse,
+ \\ SomethingThird,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: union declaration" {
+ try testCanonical(
+ \\const U = union {
+ \\ Int: u8,
+ \\ Float: f32,
+ \\ None,
+ \\ Bool: bool,
+ \\};
+ \\
+ \\const Ue = union(enum) {
+ \\ Int: u8,
+ \\ Float: f32,
+ \\ None,
+ \\ Bool: bool,
+ \\};
+ \\
+ \\const E = enum {
+ \\ Int,
+ \\ Float,
+ \\ None,
+ \\ Bool,
+ \\};
+ \\
+ \\const Ue2 = union(E) {
+ \\ Int: u8,
+ \\ Float: f32,
+ \\ None,
+ \\ Bool: bool,
+ \\};
+ \\
+ \\const Eu = extern union {
+ \\ Int: u8,
+ \\ Float: f32,
+ \\ None,
+ \\ Bool: bool,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: arrays" {
try testCanonical(
- \\test "prefix operators" {
- \\ try return --%~!&0;
+ \\test "arrays" {
+ \\ const a: [2]u32 = .{ 1, 2 };
+ \\ const b = a ++ a;
+ \\ const c = a[0..];
+ \\ _ = c;
\\}
\\
);
}
-test "zig fmt: call expression" {
+test "zig fmt: container initializers" {
try testCanonical(
- \\test "test calls" {
- \\ a();
- \\ a(1);
- \\ a(1, 2);
- \\ a(1, 2) + a(1, 2);
- \\}
+ \\const a0 = []u8{};
+ \\const a1 = []u8{1};
+ \\const a2 = []u8{
+ \\ 1,
+ \\ 2,
+ \\ 3,
+ \\ 4,
+ \\};
+ \\const s0 = S{};
+ \\const s1 = S{ .a = 1 };
+ \\const s2 = S{
+ \\ .a = 1,
+ \\ .b = 2,
+ \\};
\\
);
}
-test "zig fmt: anytype type" {
+test "zig fmt: catch" {
try testCanonical(
- \\fn print(args: anytype) @This() {}
+ \\test "catch" {
+ \\ const a: anyerror!u8 = 0;
+ \\ _ = a catch return;
+ \\ _ = a catch
+ \\ return;
+ \\ _ = a catch |err| return;
+ \\ _ = a catch |err|
+ \\ return;
+ \\}
\\
);
}
-test "zig fmt: functions" {
+test "zig fmt: blocks" {
try testCanonical(
- \\extern fn puts(s: *const u8) c_int;
- \\extern "c" fn puts(s: *const u8) c_int;
- \\export fn puts(s: *const u8) c_int;
- \\inline fn puts(s: *const u8) c_int;
- \\noinline fn puts(s: *const u8) c_int;
- \\pub extern fn puts(s: *const u8) c_int;
- \\pub extern "c" fn puts(s: *const u8) c_int;
- \\pub export fn puts(s: *const u8) c_int;
- \\pub inline fn puts(s: *const u8) c_int;
- \\pub noinline fn puts(s: *const u8) c_int;
- \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
- \\pub fn callInlineFn(func: fn () callconv(.@"inline") void) void {
- \\ func();
+ \\test {
+ \\ {
+ \\ const a = b;
+ \\ }
+ \\ const c = d;
\\}
\\
);
}
-test "zig fmt: multiline string" {
+test "zig fmt: switch" {
try testCanonical(
- \\test "" {
- \\ const s1 =
- \\ \\one
- \\ \\two)
- \\ \\three
- \\ ;
- \\ const s3 = // hi
- \\ \\one
- \\ \\two)
- \\ \\three
- \\ ;
+ \\test "switch" {
+ \\ switch (0) {
+ \\ 0 => {},
+ \\ 1 => unreachable,
+ \\ 2, 3 => {},
+ \\ 4...7 => {},
+ \\ 1 + 4 * 3 + 22 => {},
+ \\ else => {
+ \\ const a = 1;
+ \\ const b = a;
+ \\ },
+ \\ }
+ \\
+ \\ const res = switch (0) {
+ \\ 0 => 0,
+ \\ 1 => 2,
+ \\ 1 => a = 4,
+ \\ else => 4,
+ \\ };
+ \\
+ \\ const Union = union(enum) {
+ \\ Int: i64,
+ \\ Float: f64,
+ \\ };
+ \\
+ \\ switch (u) {
+ \\ Union.Int => |int| {},
+ \\ Union.Float => |*float| unreachable,
+ \\ 1 => |a, b| unreachable,
+ \\ 2 => |*a, b| unreachable,
+ \\ }
\\}
\\
);
-}
-test "zig fmt: multiline string with CRLF line endings" {
- try testTransform("" ++
- "const s =\r\n" ++
- " \\\\one\r\n" ++
- " \\\\two)\r\n" ++
- " \\\\three\r\n" ++
- ";\r\n",
- \\const s =
- \\ \\one
- \\ \\two)
- \\ \\three
- \\;
+ try testTransform(
+ \\test {
+ \\ switch (x) {
+ \\ foo =>
+ \\ "bar",
+ \\ }
+ \\}
+ \\
+ ,
+ \\test {
+ \\ switch (x) {
+ \\ foo => "bar",
+ \\ }
+ \\}
\\
);
}
-test "zig fmt: values" {
+test "zig fmt: switch multiline string" {
try testCanonical(
- \\test "values" {
- \\ 1;
- \\ 1.0;
- \\ "string";
- \\ 'c';
- \\ true;
- \\ false;
- \\ null;
- \\ undefined;
- \\ anyerror;
- \\ this;
- \\ unreachable;
+ \\test "switch multiline string" {
+ \\ const x: u32 = 0;
+ \\ const str = switch (x) {
+ \\ 1 => "one",
+ \\ 2 =>
+ \\ \\ Comma after the multiline string
+ \\ \\ is needed
+ \\ ,
+ \\ 3 => "three",
+ \\ else => "else",
+ \\ };
+ \\
+ \\ const Union = union(enum) {
+ \\ Int: i64,
+ \\ Float: f64,
+ \\ };
+ \\
+ \\ const str = switch (u) {
+ \\ Union.Int => |int|
+ \\ \\ Comma after the multiline string
+ \\ \\ is needed
+ \\ ,
+ \\ Union.Float => |*float| unreachable,
+ \\ };
\\}
\\
- );
-}
-
-test "zig fmt: indexing" {
- try testCanonical(
- \\test "test index" {
- \\ a[0];
- \\ a[0 + 5];
- \\ a[0..];
- \\ a[0..5];
- \\ a[a[0]];
- \\ a[a[0..]];
- \\ a[a[0..5]];
- \\ a[a[0]..];
- \\ a[a[0..5]..];
- \\ a[a[0]..a[0]];
- \\ a[a[0..5]..a[0]];
- \\ a[a[0..5]..a[0..5]];
+ );
+}
+
+test "zig fmt: while" {
+ try testCanonical(
+ \\test "while" {
+ \\ while (10 < 1) unreachable;
+ \\
+ \\ while (10 < 1) unreachable else unreachable;
+ \\
+ \\ while (10 < 1) {
+ \\ unreachable;
+ \\ }
+ \\
+ \\ while (10 < 1)
+ \\ unreachable;
+ \\
+ \\ var i: usize = 0;
+ \\ while (i < 10) : (i += 1) {
+ \\ continue;
+ \\ }
+ \\
+ \\ i = 0;
+ \\ while (i < 10) : (i += 1)
+ \\ continue;
+ \\
+ \\ i = 0;
+ \\ var j: usize = 0;
+ \\ while (i < 10) : ({
+ \\ i += 1;
+ \\ j += 1;
+ \\ }) continue;
+ \\
+ \\ while (i < 10) : ({
+ \\ i += 1;
+ \\ j += 1;
+ \\ }) {
+ \\ continue;
+ \\ }
+ \\
+ \\ var a: ?u8 = 2;
+ \\ while (a) |v| : (a = null) {
+ \\ continue;
+ \\ }
+ \\
+ \\ while (a) |v| : (a = null)
+ \\ continue;
+ \\
+ \\ while (a) |v| : (a = null)
+ \\ continue
+ \\ else
+ \\ unreachable;
+ \\
+ \\ for (&[_]u8{}) |v| {
+ \\ continue;
+ \\ }
+ \\
+ \\ while (a) |v| : (a = null)
+ \\ unreachable;
+ \\
+ \\ label: while (10 < 0) {
+ \\ unreachable;
+ \\ }
+ \\
+ \\ const res = while (0 < 10) {
+ \\ break 7;
+ \\ } else {
+ \\ unreachable;
+ \\ };
+ \\
+ \\ const res = while (0 < 10)
+ \\ break 7
+ \\ else
+ \\ unreachable;
+ \\
+ \\ var a: anyerror!u8 = 0;
+ \\ while (a) |v| {
+ \\ a = error.Err;
+ \\ } else |err| {
+ \\ i = 1;
+ \\ }
+ \\
+ \\ comptime var k: usize = 0;
+ \\ inline while (i < 10) : (i += 1)
+ \\ j += 2;
\\}
\\
);
}
-test "zig fmt: struct declaration" {
+test "zig fmt: for" {
try testCanonical(
- \\const S = struct {
- \\ const Self = @This();
- \\ f1: u8,
- \\ f3: u8,
+ \\test "for" {
+ \\ for (a) |v| {
+ \\ continue;
+ \\ }
\\
- \\ f2: u8,
+ \\ for (a) |v| continue;
\\
- \\ fn method(self: *Self) Self {
- \\ return self.*;
+ \\ for (a) |v| continue else return;
+ \\
+ \\ for (a) |v| {
+ \\ continue;
+ \\ } else return;
+ \\
+ \\ for (a) |v| continue else {
+ \\ return;
\\ }
- \\};
\\
- \\const Ps = packed struct {
- \\ a: u8,
- \\ b: u8,
+ \\ for (a) |v|
+ \\ continue
+ \\ else
+ \\ return;
\\
- \\ c: u8,
- \\};
+ \\ for (a) |v|
+ \\ continue;
\\
- \\const Ps = packed struct(u32) {
- \\ a: u1,
- \\ b: u2,
+ \\ for (a) |*v|
+ \\ continue;
\\
- \\ c: u29,
- \\};
+ \\ for (a, 0..) |v, i| {
+ \\ continue;
+ \\ }
\\
- \\const Es = extern struct {
- \\ a: u8,
- \\ b: u8,
+ \\ for (a, 0..) |v, i|
+ \\ continue;
\\
- \\ c: u8,
- \\};
+ \\ for (a) |b| switch (b) {
+ \\ c => {},
+ \\ d => {},
+ \\ };
+ \\
+ \\ const res = for (a, 0..) |v, i| {
+ \\ break v;
+ \\ } else {
+ \\ unreachable;
+ \\ };
+ \\
+ \\ var num: usize = 0;
+ \\ inline for (a, 0..1) |v, i| {
+ \\ num += v;
+ \\ num += i;
+ \\ }
+ \\
+ \\ for (a, b) |
+ \\ long_name,
+ \\ another_long_name,
+ \\ | {
+ \\ continue;
+ \\ }
+ \\}
\\
);
-}
-test "zig fmt: enum declaration" {
- try testCanonical(
- \\const E = enum {
- \\ Ok,
- \\ SomethingElse = 0,
- \\};
+ try testTransform(
+ \\test "fix for" {
+ \\ for (a) |x|
+ \\ f(x) else continue;
+ \\}
\\
- \\const E2 = enum(u8) {
- \\ Ok,
- \\ SomethingElse = 255,
- \\ SomethingThird,
- \\};
+ ,
+ \\test "fix for" {
+ \\ for (a) |x|
+ \\ f(x)
+ \\ else
+ \\ continue;
+ \\}
\\
- \\const Ee = extern enum {
- \\ Ok,
- \\ SomethingElse,
- \\ SomethingThird,
- \\};
+ );
+
+ try testTransform(
+ \\test "fix for" {
+ \\ for (a, b, c,) |long, another, third,| {}
+ \\}
\\
- \\const Ep = packed enum {
- \\ Ok,
- \\ SomethingElse,
- \\ SomethingThird,
- \\};
+ ,
+ \\test "fix for" {
+ \\ for (
+ \\ a,
+ \\ b,
+ \\ c,
+ \\ ) |
+ \\ long,
+ \\ another,
+ \\ third,
+ \\ | {}
+ \\}
\\
);
}
-test "zig fmt: union declaration" {
+test "zig fmt: for if" {
try testCanonical(
- \\const U = union {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
- \\
- \\const Ue = union(enum) {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
+ \\test {
+ \\ for (a) |x| if (x) f(x);
\\
- \\const E = enum {
- \\ Int,
- \\ Float,
- \\ None,
- \\ Bool,
- \\};
+ \\ for (a) |x| if (x)
+ \\ f(x);
\\
- \\const Ue2 = union(E) {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
+ \\ for (a) |x| if (x) {
+ \\ f(x);
+ \\ };
\\
- \\const Eu = extern union {
- \\ Int: u8,
- \\ Float: f32,
- \\ None,
- \\ Bool: bool,
- \\};
+ \\ for (a) |x|
+ \\ if (x)
+ \\ f(x);
\\
- );
-}
-
-test "zig fmt: arrays" {
- try testCanonical(
- \\test "arrays" {
- \\ const a: [2]u32 = .{ 1, 2 };
- \\ const b = a ++ a;
- \\ const c = a[0..];
- \\ _ = c;
+ \\ for (a) |x|
+ \\ if (x) {
+ \\ f(x);
+ \\ };
\\}
\\
);
}
-test "zig fmt: container initializers" {
+test "zig fmt: if for" {
try testCanonical(
- \\const a0 = []u8{};
- \\const a1 = []u8{1};
- \\const a2 = []u8{
- \\ 1,
- \\ 2,
- \\ 3,
- \\ 4,
- \\};
- \\const s0 = S{};
- \\const s1 = S{ .a = 1 };
- \\const s2 = S{
- \\ .a = 1,
- \\ .b = 2,
- \\};
+ \\test {
+ \\ if (a) for (x) |x| f(x);
\\
- );
-}
-
-test "zig fmt: catch" {
- try testCanonical(
- \\test "catch" {
- \\ const a: anyerror!u8 = 0;
- \\ _ = a catch return;
- \\ _ = a catch
- \\ return;
- \\ _ = a catch |err| return;
- \\ _ = a catch |err|
- \\ return;
+ \\ if (a) for (x) |x|
+ \\ f(x);
+ \\
+ \\ if (a) for (x) |x| {
+ \\ f(x);
+ \\ };
+ \\
+ \\ if (a)
+ \\ for (x) |x|
+ \\ f(x);
+ \\
+ \\ if (a)
+ \\ for (x) |x| {
+ \\ f(x);
+ \\ };
\\}
\\
);
}
-test "zig fmt: blocks" {
+test "zig fmt: while if" {
try testCanonical(
\\test {
- \\ {
- \\ const a = b;
- \\ }
- \\ const c = d;
+ \\ while (a) if (x) f(x);
+ \\
+ \\ while (a) if (x)
+ \\ f(x);
+ \\
+ \\ while (a) if (x) {
+ \\ f(x);
+ \\ };
+ \\
+ \\ while (a)
+ \\ if (x)
+ \\ f(x);
+ \\
+ \\ while (a)
+ \\ if (x) {
+ \\ f(x);
+ \\ };
\\}
\\
);
}
-test "zig fmt: switch" {
+test "zig fmt: if while" {
try testCanonical(
- \\test "switch" {
- \\ switch (0) {
- \\ 0 => {},
- \\ 1 => unreachable,
- \\ 2, 3 => {},
- \\ 4...7 => {},
- \\ 1 + 4 * 3 + 22 => {},
- \\ else => {
- \\ const a = 1;
- \\ const b = a;
- \\ },
- \\ }
+ \\test {
+ \\ if (a) while (x) : (cont) f(x);
\\
- \\ const res = switch (0) {
- \\ 0 => 0,
- \\ 1 => 2,
- \\ 1 => a = 4,
- \\ else => 4,
- \\ };
+ \\ if (a) while (x) : (cont)
+ \\ f(x);
\\
- \\ const Union = union(enum) {
- \\ Int: i64,
- \\ Float: f64,
+ \\ if (a) while (x) : (cont) {
+ \\ f(x);
\\ };
\\
- \\ switch (u) {
- \\ Union.Int => |int| {},
- \\ Union.Float => |*float| unreachable,
- \\ 1 => |a, b| unreachable,
- \\ 2 => |*a, b| unreachable,
- \\ }
+ \\ if (a)
+ \\ while (x) : (cont)
+ \\ f(x);
+ \\
+ \\ if (a)
+ \\ while (x) : (cont) {
+ \\ f(x);
+ \\ };
\\}
\\
);
+}
- try testTransform(
+test "zig fmt: while for" {
+ try testCanonical(
\\test {
- \\ switch (x) {
- \\ foo =>
- \\ "bar",
- \\ }
- \\}
+ \\ while (a) for (x) |x| f(x);
\\
- ,
- \\test {
- \\ switch (x) {
- \\ foo => "bar",
- \\ }
+ \\ while (a) for (x) |x|
+ \\ f(x);
+ \\
+ \\ while (a) for (x) |x| {
+ \\ f(x);
+ \\ };
+ \\
+ \\ while (a)
+ \\ for (x) |x|
+ \\ f(x);
+ \\
+ \\ while (a)
+ \\ for (x) |x| {
+ \\ f(x);
+ \\ };
\\}
\\
);
}
-test "zig fmt: switch multiline string" {
+test "zig fmt: for while" {
try testCanonical(
- \\test "switch multiline string" {
- \\ const x: u32 = 0;
- \\ const str = switch (x) {
- \\ 1 => "one",
- \\ 2 =>
- \\ \\ Comma after the multiline string
- \\ \\ is needed
- \\ ,
- \\ 3 => "three",
- \\ else => "else",
- \\ };
+ \\test {
+ \\ for (a) |a| while (x) |x| f(x);
\\
- \\ const Union = union(enum) {
- \\ Int: i64,
- \\ Float: f64,
- \\ };
+ \\ for (a) |a| while (x) |x|
+ \\ f(x);
\\
- \\ const str = switch (u) {
- \\ Union.Int => |int|
- \\ \\ Comma after the multiline string
- \\ \\ is needed
- \\ ,
- \\ Union.Float => |*float| unreachable,
+ \\ for (a) |a| while (x) |x| {
+ \\ f(x);
\\ };
+ \\
+ \\ for (a) |a|
+ \\ while (x) |x|
+ \\ f(x);
+ \\
+ \\ for (a) |a|
+ \\ while (x) |x| {
+ \\ f(x);
+ \\ };
\\}
\\
);
}
-test "zig fmt: while" {
+test "zig fmt: if" {
try testCanonical(
- \\test "while" {
- \\ while (10 < 1) unreachable;
+ \\test "if" {
+ \\ if (10 < 0) {
+ \\ unreachable;
+ \\ }
\\
- \\ while (10 < 1) unreachable else unreachable;
+ \\ if (10 < 0) unreachable;
\\
- \\ while (10 < 1) {
+ \\ if (10 < 0) {
\\ unreachable;
+ \\ } else {
+ \\ const a = 20;
\\ }
\\
- \\ while (10 < 1)
+ \\ if (10 < 0) {
\\ unreachable;
- \\
- \\ var i: usize = 0;
- \\ while (i < 10) : (i += 1) {
- \\ continue;
+ \\ } else if (5 < 0) {
+ \\ unreachable;
+ \\ } else {
+ \\ const a = 20;
\\ }
\\
- \\ i = 0;
- \\ while (i < 10) : (i += 1)
- \\ continue;
- \\
- \\ i = 0;
- \\ var j: usize = 0;
- \\ while (i < 10) : ({
- \\ i += 1;
- \\ j += 1;
- \\ }) continue;
+ \\ const is_world_broken = if (10 < 0) true else false;
+ \\ const some_number = 1 + if (10 < 0) 2 else 3;
\\
- \\ while (i < 10) : ({
- \\ i += 1;
- \\ j += 1;
- \\ }) {
- \\ continue;
+ \\ const a: ?u8 = 10;
+ \\ const b: ?u8 = null;
+ \\ if (a) |v| {
+ \\ const some = v;
+ \\ } else if (b) |*v| {
+ \\ unreachable;
+ \\ } else {
+ \\ const some = 10;
\\ }
\\
- \\ var a: ?u8 = 2;
- \\ while (a) |v| : (a = null) {
- \\ continue;
+ \\ const non_null_a = if (a) |v| v else 0;
+ \\
+ \\ const a_err: anyerror!u8 = 0;
+ \\ if (a_err) |v| {
+ \\ const p = v;
+ \\ } else |err| {
+ \\ unreachable;
\\ }
+ \\}
\\
- \\ while (a) |v| : (a = null)
- \\ continue;
+ );
+}
+
+test "zig fmt: fix single statement if/for/while line breaks" {
+ try testTransform(
+ \\test {
+ \\ if (cond) a
+ \\ else b;
\\
- \\ while (a) |v| : (a = null)
- \\ continue
+ \\ if (cond)
+ \\ a
+ \\ else b;
+ \\
+ \\ for (xs) |x| foo()
+ \\ else bar();
+ \\
+ \\ for (xs) |x|
+ \\ foo()
+ \\ else bar();
+ \\
+ \\ while (a) : (b) foo()
+ \\ else bar();
+ \\
+ \\ while (a) : (b)
+ \\ foo()
+ \\ else bar();
+ \\}
+ \\
+ ,
+ \\test {
+ \\ if (cond) a else b;
+ \\
+ \\ if (cond)
+ \\ a
\\ else
- \\ unreachable;
+ \\ b;
+ \\
+ \\ for (xs) |x| foo() else bar();
+ \\
+ \\ for (xs) |x|
+ \\ foo()
+ \\ else
+ \\ bar();
+ \\
+ \\ while (a) : (b) foo() else bar();
+ \\
+ \\ while (a) : (b)
+ \\ foo()
+ \\ else
+ \\ bar();
+ \\}
\\
- \\ for (&[_]u8{}) |v| {
- \\ continue;
+ );
+}
+
+test "zig fmt: defer" {
+ try testCanonical(
+ \\test "defer" {
+ \\ defer foo();
+ \\ defer {
+ \\ bar();
\\ }
+ \\}
\\
- \\ while (a) |v| : (a = null)
- \\ unreachable;
- \\
- \\ label: while (10 < 0) {
- \\ unreachable;
+ );
+}
+
+test "zig fmt: comptime" {
+ try testCanonical(
+ \\fn foo() void {
+ \\ comptime {
+ \\ bar();
\\ }
+ \\}
\\
- \\ const res = while (0 < 10) {
- \\ break 7;
- \\ } else {
- \\ unreachable;
- \\ };
+ );
+}
+
+test "zig fmt: fn type" {
+ try testCanonical(
+ \\fn a(i: u8) u8 {
+ \\ return i + 1;
+ \\}
\\
- \\ const res = while (0 < 10)
- \\ break 7
- \\ else
- \\ unreachable;
+ \\const a: fn (u8) u8 = undefined;
+ \\const b: fn (u8) callconv(.naked) u8 = undefined;
+ \\const ap: fn (u8) u8 = a;
\\
- \\ var a: anyerror!u8 = 0;
- \\ while (a) |v| {
- \\ a = error.Err;
- \\ } else |err| {
- \\ i = 1;
- \\ }
+ );
+}
+
+test "zig fmt: inline asm" {
+ try testTransform(
+ \\pub fn syscall1(number: usize, arg1: usize) usize {
+ \\ return asm volatile ("syscall"
+ \\ : [ret] "={rax}" (-> usize),
+ \\ : [number] "{rax}" (number),
+ \\ [arg1] "{rdi}" (arg1),
+ \\ : "rcx", "r11"
+ \\ );
+ \\}
\\
- \\ comptime var k: usize = 0;
- \\ inline while (i < 10) : (i += 1)
- \\ j += 2;
+ ,
+ \\pub fn syscall1(number: usize, arg1: usize) usize {
+ \\ return asm volatile ("syscall"
+ \\ : [ret] "={rax}" (-> usize),
+ \\ : [number] "{rax}" (number),
+ \\ [arg1] "{rdi}" (arg1),
+ \\ : .{ .rcx = true, .r11 = true }
+ \\ );
\\}
\\
);
}
-test "zig fmt: for" {
+test "zig fmt: nosuspend" {
try testCanonical(
- \\test "for" {
- \\ for (a) |v| {
- \\ continue;
+ \\const a = nosuspend foo();
+ \\
+ );
+}
+
+test "zig fmt: Block after if" {
+ try testCanonical(
+ \\test {
+ \\ if (true) {
+ \\ const a = 0;
\\ }
\\
- \\ for (a) |v| continue;
+ \\ {
+ \\ const a = 0;
+ \\ }
+ \\}
\\
- \\ for (a) |v| continue else return;
+ );
+}
+
+test "zig fmt: string identifier" {
+ try testCanonical(
+ \\const @"a b" = @"c d".@"e f";
+ \\fn @"g h"() void {}
\\
- \\ for (a) |v| {
- \\ continue;
- \\ } else return;
+ );
+}
+
+test "zig fmt: error return" {
+ try testCanonical(
+ \\fn err() anyerror {
+ \\ call();
+ \\ return error.InvalidArgs;
+ \\}
\\
- \\ for (a) |v| continue else {
- \\ return;
+ );
+}
+
+test "zig fmt: comptime block in container" {
+ try testCanonical(
+ \\const Foo = struct {
+ \\ comptime {
+ \\ @compileLog("hello comptime");
\\ }
+ \\};
\\
- \\ for (a) |v|
- \\ continue
- \\ else
- \\ return;
+ );
+}
+
+test "zig fmt: inline asm parameter alignment" {
+ try testCanonical(
+ \\pub fn main() void {
+ \\ asm volatile (
+ \\ \\ foo
+ \\ \\ bar
+ \\ );
+ \\ asm volatile (
+ \\ \\ foo
+ \\ \\ bar
+ \\ : [_] "" (-> usize),
+ \\ [_] "" (-> usize),
+ \\ );
+ \\ asm volatile (
+ \\ \\ foo
+ \\ \\ bar
+ \\ :
+ \\ : [_] "" (0),
+ \\ [_] "" (0),
+ \\ );
+ \\ asm volatile (
+ \\ \\ foo
+ \\ \\ bar
+ \\ ::: .{ .a = true, .b = true });
+ \\ asm volatile (
+ \\ \\ foo
+ \\ \\ bar
+ \\ : [_] "" (-> usize),
+ \\ [_] "" (-> usize),
+ \\ : [_] "" (0),
+ \\ [_] "" (0),
+ \\ : .{});
+ \\}
\\
- \\ for (a) |v|
- \\ continue;
+ );
+}
+
+test "zig fmt: multiline string in array" {
+ try testCanonical(
+ \\const Foo = [][]const u8{
+ \\ \\aaa
+ \\ ,
+ \\ \\bbb
+ \\};
\\
- \\ for (a) |*v|
- \\ continue;
+ \\fn bar() void {
+ \\ const Foo = [][]const u8{
+ \\ \\aaa
+ \\ ,
+ \\ \\bbb
+ \\ };
+ \\ const Bar = [][]const u8{ // comment here
+ \\ \\aaa
+ \\ \\
+ \\ , // and another comment can go here
+ \\ \\bbb
+ \\ };
+ \\}
\\
- \\ for (a, 0..) |v, i| {
- \\ continue;
- \\ }
+ );
+}
+
+test "zig fmt: file ends with struct field" {
+ try testCanonical(
+ \\a: bool
\\
- \\ for (a, 0..) |v, i|
- \\ continue;
+ );
+}
+
+test "zig fmt: comment after empty comment" {
+ try testCanonical(
+ \\//
+ \\/// A doc comment
+ \\const a = b;
\\
- \\ for (a) |b| switch (b) {
- \\ c => {},
- \\ d => {},
+ );
+}
+
+test "zig fmt: line comment in array" {
+ try testTransform(
+ \\test "a" {
+ \\ var arr = [_]u32{
+ \\ 0
+ \\ // 1,
+ \\ // 2,
\\ };
+ \\}
\\
- \\ const res = for (a, 0..) |v, i| {
- \\ break v;
- \\ } else {
- \\ unreachable;
+ ,
+ \\test "a" {
+ \\ var arr = [_]u32{
+ \\ 0,
+ \\ // 1,
+ \\ // 2,
\\ };
+ \\}
\\
- \\ var num: usize = 0;
- \\ inline for (a, 0..1) |v, i| {
- \\ num += v;
- \\ num += i;
- \\ }
- \\
- \\ for (a, b) |
- \\ long_name,
- \\ another_long_name,
- \\ | {
- \\ continue;
- \\ }
+ );
+ try testCanonical(
+ \\test "a" {
+ \\ var arr = [_]u32{
+ \\ 0,
+ \\ // 1,
+ \\ // 2,
+ \\ };
\\}
\\
);
+}
- try testTransform(
- \\test "fix for" {
- \\ for (a) |x|
- \\ f(x) else continue;
- \\}
+test "zig fmt: comment after params" {
+ try testCanonical(
+ \\fn foo(
+ \\ a: i32, // comment
+ \\ b: i32, // comment
+ \\) void {}
\\
- ,
- \\test "fix for" {
- \\ for (a) |x|
- \\ f(x)
- \\ else
- \\ continue;
+ );
+}
+
+test "zig fmt: comment in array initializer/access" {
+ try testCanonical(
+ \\test "a" {
+ \\ var a = x{ //aa
+ \\ //bb
+ \\ };
+ \\ var a = []x{ //aa
+ \\ //bb
+ \\ };
+ \\ var b = [ //aa
+ \\ _
+ \\ ]x{ //aa
+ \\ //bb
+ \\ 9,
+ \\ };
+ \\ var c = b[ //aa
+ \\ 0
+ \\ ];
+ \\ var d = [
+ \\ _
+ \\ //aa
+ \\ :
+ \\ 0
+ \\ ]x{ //aa
+ \\ //bb
+ \\ 9,
+ \\ };
+ \\ var e = d[
+ \\ 0
+ \\ //aa
+ \\ ];
\\}
\\
);
+}
+test "zig fmt: comments at several places in struct init" {
try testTransform(
- \\test "fix for" {
- \\ for (a, b, c,) |long, another, third,| {}
- \\}
+ \\var bar = Bar{
+ \\ .x = 10, // test
+ \\ .y = "test"
+ \\ // test
+ \\};
\\
,
- \\test "fix for" {
- \\ for (
- \\ a,
- \\ b,
- \\ c,
- \\ ) |
- \\ long,
- \\ another,
- \\ third,
- \\ | {}
- \\}
+ \\var bar = Bar{
+ \\ .x = 10, // test
+ \\ .y = "test",
+ \\ // test
+ \\};
+ \\
+ );
+
+ try testCanonical(
+ \\var bar = Bar{ // test
+ \\ .x = 10, // test
+ \\ .y = "test",
+ \\ // test
+ \\};
\\
);
}
-test "zig fmt: for if" {
+test "zig fmt: container doc comments" {
try testCanonical(
- \\test {
- \\ for (a) |x| if (x) f(x);
+ \\//! tld 1
+ \\//! tld 2
+ \\//! tld 3
+ \\const a = b;
\\
- \\ for (a) |x| if (x)
- \\ f(x);
+ );
+}
+
+test "zig fmt: remove newlines surrounding doc comment" {
+ try testTransform(
\\
- \\ for (a) |x| if (x) {
- \\ f(x);
- \\ };
\\
- \\ for (a) |x|
- \\ if (x)
- \\ f(x);
\\
- \\ for (a) |x|
- \\ if (x) {
- \\ f(x);
- \\ };
- \\}
+ \\/// doc comment
+ \\
+ \\fn foo() void {}
+ \\
+ ,
+ \\/// doc comment
+ \\fn foo() void {}
\\
);
}
-test "zig fmt: if for" {
- try testCanonical(
- \\test {
- \\ if (a) for (x) |x| f(x);
+test "zig fmt: remove newlines surrounding doc comment between members" {
+ try testTransform(
+ \\f1: i32,
\\
- \\ if (a) for (x) |x|
- \\ f(x);
\\
- \\ if (a) for (x) |x| {
- \\ f(x);
- \\ };
+ \\/// doc comment
\\
- \\ if (a)
- \\ for (x) |x|
- \\ f(x);
+ \\f2: i32,
\\
- \\ if (a)
- \\ for (x) |x| {
- \\ f(x);
- \\ };
- \\}
+ ,
+ \\f1: i32,
+ \\
+ \\/// doc comment
+ \\f2: i32,
\\
);
}
-test "zig fmt: while if" {
- try testCanonical(
- \\test {
- \\ while (a) if (x) f(x);
+test "zig fmt: remove newlines surrounding doc comment between members within container decl (1)" {
+ try testTransform(
+ \\const Foo = struct {
+ \\ fn foo() void {}
\\
- \\ while (a) if (x)
- \\ f(x);
\\
- \\ while (a) if (x) {
- \\ f(x);
- \\ };
+ \\ /// doc comment
\\
- \\ while (a)
- \\ if (x)
- \\ f(x);
\\
- \\ while (a)
- \\ if (x) {
- \\ f(x);
- \\ };
- \\}
+ \\ fn bar() void {}
+ \\};
+ \\
+ ,
+ \\const Foo = struct {
+ \\ fn foo() void {}
+ \\
+ \\ /// doc comment
+ \\ fn bar() void {}
+ \\};
\\
);
}
-test "zig fmt: if while" {
- try testCanonical(
- \\test {
- \\ if (a) while (x) : (cont) f(x);
- \\
- \\ if (a) while (x) : (cont)
- \\ f(x);
+test "zig fmt: remove newlines surrounding doc comment between members within container decl (2)" {
+ try testTransform(
+ \\const Foo = struct {
+ \\ fn foo() void {}
+ \\ /// doc comment 1
\\
- \\ if (a) while (x) : (cont) {
- \\ f(x);
- \\ };
+ \\ /// doc comment 2
\\
- \\ if (a)
- \\ while (x) : (cont)
- \\ f(x);
+ \\ fn bar() void {}
+ \\};
\\
- \\ if (a)
- \\ while (x) : (cont) {
- \\ f(x);
- \\ };
- \\}
+ ,
+ \\const Foo = struct {
+ \\ fn foo() void {}
+ \\ /// doc comment 1
+ \\ /// doc comment 2
+ \\ fn bar() void {}
+ \\};
\\
);
}
-test "zig fmt: while for" {
- try testCanonical(
- \\test {
- \\ while (a) for (x) |x| f(x);
+test "zig fmt: remove newlines surrounding doc comment within container decl" {
+ try testTransform(
+ \\const Foo = struct {
\\
- \\ while (a) for (x) |x|
- \\ f(x);
\\
- \\ while (a) for (x) |x| {
- \\ f(x);
- \\ };
+ \\ /// doc comment
\\
- \\ while (a)
- \\ for (x) |x|
- \\ f(x);
+ \\ fn foo() void {}
+ \\};
\\
- \\ while (a)
- \\ for (x) |x| {
- \\ f(x);
- \\ };
- \\}
+ ,
+ \\const Foo = struct {
+ \\ /// doc comment
+ \\ fn foo() void {}
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: comments with CRLF line endings" {
+ try testTransform("" ++
+ "//! Top-level doc comment\r\n" ++
+ "//! Continuing to another line\r\n" ++
+ "\r\n" ++
+ "/// Regular doc comment\r\n" ++
+ "const S = struct {\r\n" ++
+ " // Regular comment\r\n" ++
+ " // More content\r\n" ++
+ "};\r\n",
+ \\//! Top-level doc comment
+ \\//! Continuing to another line
+ \\
+ \\/// Regular doc comment
+ \\const S = struct {
+ \\ // Regular comment
+ \\ // More content
+ \\};
\\
);
}
-test "zig fmt: for while" {
+test "zig fmt: else comptime expr" {
try testCanonical(
- \\test {
- \\ for (a) |a| while (x) |x| f(x);
- \\
- \\ for (a) |a| while (x) |x|
- \\ f(x);
- \\
- \\ for (a) |a| while (x) |x| {
- \\ f(x);
- \\ };
- \\
- \\ for (a) |a|
- \\ while (x) |x|
- \\ f(x);
- \\
- \\ for (a) |a|
- \\ while (x) |x| {
- \\ f(x);
- \\ };
+ \\comptime {
+ \\ if (true) {} else comptime foo();
+ \\}
+ \\comptime {
+ \\ while (true) {} else comptime foo();
+ \\}
+ \\comptime {
+ \\ for ("") |_| {} else comptime foo();
\\}
\\
);
}
-test "zig fmt: if" {
- try testCanonical(
- \\test "if" {
- \\ if (10 < 0) {
- \\ unreachable;
- \\ }
- \\
- \\ if (10 < 0) unreachable;
- \\
- \\ if (10 < 0) {
- \\ unreachable;
- \\ } else {
- \\ const a = 20;
- \\ }
- \\
- \\ if (10 < 0) {
- \\ unreachable;
- \\ } else if (5 < 0) {
- \\ unreachable;
- \\ } else {
- \\ const a = 20;
- \\ }
- \\
- \\ const is_world_broken = if (10 < 0) true else false;
- \\ const some_number = 1 + if (10 < 0) 2 else 3;
+test "zig fmt: integer literals with underscore separators" {
+ try testTransform(
+ \\const
+ \\ x =
+ \\ 1_234_567
+ \\ + (0b0_1-0o7_0+0xff_FF ) + 1_0;
+ ,
+ \\const x =
+ \\ 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 1_0;
\\
- \\ const a: ?u8 = 10;
- \\ const b: ?u8 = null;
- \\ if (a) |v| {
- \\ const some = v;
- \\ } else if (b) |*v| {
- \\ unreachable;
- \\ } else {
- \\ const some = 10;
+ );
+}
+
+test "zig fmt: hex literals with underscore separators" {
+ try testTransform(
+ \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
+ \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
+ \\ for (c [ 1_0 .. ], 0..) |_, i| {
+ \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
\\ }
+ \\ return c;
+ \\}
\\
- \\ const non_null_a = if (a) |v| v else 0;
\\
- \\ const a_err: anyerror!u8 = 0;
- \\ if (a_err) |v| {
- \\ const p = v;
- \\ } else |err| {
- \\ unreachable;
+ ,
+ \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
+ \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
+ \\ for (c[1_0..], 0..) |_, i| {
+ \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
\\ }
+ \\ return c;
\\}
\\
);
}
-test "zig fmt: fix single statement if/for/while line breaks" {
- try testTransform(
- \\test {
- \\ if (cond) a
- \\ else b;
- \\
- \\ if (cond)
- \\ a
- \\ else b;
- \\
- \\ for (xs) |x| foo()
- \\ else bar();
- \\
- \\ for (xs) |x|
- \\ foo()
- \\ else bar();
- \\
- \\ while (a) : (b) foo()
- \\ else bar();
+test "zig fmt: decimal float literals with underscore separators" {
+ try testCanonical(
+ \\const x = 1_234_567.89_10_11;
+ \\const y = 1_234_567.89_10_11e1_213_14;
+ \\const z = 1_234_567;
\\
- \\ while (a) : (b)
- \\ foo()
- \\ else bar();
+ );
+}
+
+test "zig fmt: hexadecimal float literals with underscore separators" {
+ try testTransform(
+ \\pub fn main() void {
+ \\ const a: f64 = (0x10.0p-0+(0x10.0p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
+ \\ const b: f64 = 0x0010.0--0x00_10.0+0x10.00+0x1p4;
+ \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
\\}
- \\
,
- \\test {
- \\ if (cond) a else b;
- \\
- \\ if (cond)
- \\ a
- \\ else
- \\ b;
- \\
- \\ for (xs) |x| foo() else bar();
- \\
- \\ for (xs) |x|
- \\ foo()
- \\ else
- \\ bar();
+ \\pub fn main() void {
+ \\ const a: f64 = (0x10.0p-0 + (0x10.0p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
+ \\ const b: f64 = 0x0010.0 - -0x00_10.0 + 0x10.00 + 0x1p4;
+ \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
+ \\}
\\
- \\ while (a) : (b) foo() else bar();
+ );
+}
+
+test "zig fmt: C var args" {
+ try testCanonical(
+ \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
\\
- \\ while (a) : (b)
- \\ foo()
- \\ else
- \\ bar();
+ );
+}
+
+test "zig fmt: Only indent multiline string literals in function calls" {
+ try testCanonical(
+ \\test "zig fmt:" {
+ \\ try testTransform(
+ \\ \\const X = struct {
+ \\ \\ foo: i32, bar: i8 };
+ \\ ,
+ \\ \\const X = struct {
+ \\ \\ foo: i32, bar: i8
+ \\ \\};
+ \\ \\
+ \\ );
\\}
\\
);
}
-test "zig fmt: defer" {
+test "zig fmt: Don't add extra newline after if" {
try testCanonical(
- \\test "defer" {
- \\ defer foo();
- \\ defer {
- \\ bar();
+ \\pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void {
+ \\ if (cwd().symLink(existing_path, new_path, .{})) {
+ \\ return;
\\ }
\\}
\\
);
}
-test "zig fmt: comptime" {
+test "zig fmt: comments in ternary ifs" {
try testCanonical(
- \\fn foo() void {
- \\ comptime {
- \\ bar();
- \\ }
- \\}
+ \\const x = if (true) {
+ \\ 1;
+ \\} else if (false)
+ \\ // Comment
+ \\ 0;
+ \\const y = if (true)
+ \\ // Comment
+ \\ 1
+ \\else
+ \\ // Comment
+ \\ 0;
+ \\
+ \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
\\
);
}
-test "zig fmt: fn type" {
+test "zig fmt: while statement in blockless if" {
try testCanonical(
- \\fn a(i: u8) u8 {
- \\ return i + 1;
+ \\pub fn main() void {
+ \\ const zoom_node = if (focused_node == layout_first)
+ \\ while (it.next()) |node| {
+ \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+ \\ } else null
+ \\ else
+ \\ focused_node;
\\}
\\
- \\const a: fn (u8) u8 = undefined;
- \\const b: fn (u8) callconv(.naked) u8 = undefined;
- \\const ap: fn (u8) u8 = a;
+ );
+}
+
+test "zig fmt: test comments in field access chain" {
+ try testCanonical(
+ \\pub const str = struct {
+ \\ pub const Thing = more.more //
+ \\ .more() //
+ \\ .more().more() //
+ \\ .more() //
+ \\ // .more() //
+ \\ .more() //
+ \\ .more();
+ \\ data: Data,
+ \\};
+ \\
+ \\pub const str = struct {
+ \\ pub const Thing = more.more //
+ \\ .more() //
+ \\ // .more() //
+ \\ // .more() //
+ \\ // .more() //
+ \\ .more() //
+ \\ .more();
+ \\ data: Data,
+ \\};
+ \\
+ \\pub const str = struct {
+ \\ pub const Thing = more //
+ \\ .more //
+ \\ .more() //
+ \\ .more();
+ \\ data: Data,
+ \\};
\\
);
}
-test "zig fmt: inline asm" {
- try testTransform(
- \\pub fn syscall1(number: usize, arg1: usize) usize {
- \\ return asm volatile ("syscall"
- \\ : [ret] "={rax}" (-> usize),
- \\ : [number] "{rax}" (number),
- \\ [arg1] "{rdi}" (arg1),
- \\ : "rcx", "r11"
- \\ );
- \\}
+test "zig fmt: allow line break before field access" {
+ try testCanonical(
+ \\test {
+ \\ const w = foo.bar().zippy(zag).iguessthisisok();
\\
- ,
- \\pub fn syscall1(number: usize, arg1: usize) usize {
- \\ return asm volatile ("syscall"
- \\ : [ret] "={rax}" (-> usize),
- \\ : [number] "{rax}" (number),
- \\ [arg1] "{rdi}" (arg1),
- \\ : .{ .rcx = true, .r11 = true }
- \\ );
+ \\ const x = foo
+ \\ .bar()
+ \\ . // comment
+ \\ // comment
+ \\ swooop().zippy(zag)
+ \\ .iguessthisisok();
+ \\
+ \\ const y = view.output.root.server.input_manager.default_seat.wlr_seat.name;
+ \\
+ \\ const z = view.output.root.server
+ \\ .input_manager //
+ \\ .default_seat
+ \\ . // comment
+ \\ // another comment
+ \\ wlr_seat.name;
\\}
\\
);
-}
-
-test "zig fmt: nosuspend" {
- try testCanonical(
- \\const a = nosuspend foo();
+ try testTransform(
+ \\test {
+ \\ const x = foo.
+ \\ bar()
+ \\ .zippy(zag).iguessthisisok();
\\
- );
-}
-
-test "zig fmt: Block after if" {
- try testCanonical(
+ \\ const z = view.output.root.server.
+ \\ input_manager.
+ \\ default_seat.wlr_seat.name;
+ \\}
+ \\
+ ,
\\test {
- \\ if (true) {
- \\ const a = 0;
- \\ }
+ \\ const x = foo
+ \\ .bar()
+ \\ .zippy(zag).iguessthisisok();
\\
- \\ {
- \\ const a = 0;
- \\ }
+ \\ const z = view.output.root.server
+ \\ .input_manager
+ \\ .default_seat.wlr_seat.name;
\\}
\\
);
}
-test "zig fmt: string identifier" {
+test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
try testCanonical(
- \\const @"a b" = @"c d".@"e f";
- \\fn @"g h"() void {}
+ \\fn foo() void {
+ \\ z.display_message_dialog(
+ \\ *const [323:0]u8,
+ \\ \\Message Text
+ \\ \\------------
+ \\ \\xxxxxxxxxxxx
+ \\ \\xxxxxxxxxxxx
+ \\ ,
+ \\ g.GtkMessageType.GTK_MESSAGE_WARNING,
+ \\ null,
+ \\ );
+ \\
+ \\ z.display_message_dialog(*const [323:0]u8,
+ \\ \\Message Text
+ \\ \\------------
+ \\ \\xxxxxxxxxxxx
+ \\ \\xxxxxxxxxxxx
+ \\ , g.GtkMessageType.GTK_MESSAGE_WARNING, null);
+ \\}
\\
);
}
-test "zig fmt: error return" {
+test "zig fmt: regression test for #5722" {
try testCanonical(
- \\fn err() anyerror {
- \\ call();
- \\ return error.InvalidArgs;
+ \\pub fn sendViewTags(self: Self) void {
+ \\ var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));
+ \\ while (it.next()) |node|
+ \\ view_tags.append(node.view.current_tags) catch {
+ \\ c.wl_resource_post_no_memory(self.wl_resource);
+ \\ log.err(.river_status, "out of memory", .{});
+ \\ return;
+ \\ };
\\}
\\
);
}
-test "zig fmt: comptime block in container" {
+test "zig fmt: regression test for #8974" {
try testCanonical(
- \\const Foo = struct {
- \\ comptime {
- \\ @compileLog("hello comptime");
- \\ }
- \\};
+ \\pub const VARIABLE;
\\
);
}
-test "zig fmt: inline asm parameter alignment" {
+test "zig fmt: allow trailing line comments to do manual array formatting" {
try testCanonical(
- \\pub fn main() void {
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ );
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ : [_] "" (-> usize),
- \\ [_] "" (-> usize),
- \\ );
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ :
- \\ : [_] "" (0),
- \\ [_] "" (0),
- \\ );
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ ::: .{ .a = true, .b = true });
- \\ asm volatile (
- \\ \\ foo
- \\ \\ bar
- \\ : [_] "" (-> usize),
- \\ [_] "" (-> usize),
- \\ : [_] "" (0),
- \\ [_] "" (0),
- \\ : .{});
+ \\fn foo() void {
+ \\ self.code.appendSliceAssumeCapacity(&[_]u8{
+ \\ 0x55, // push rbp
+ \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
+ \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
+ \\ });
+ \\
+ \\ di_buf.appendAssumeCapacity(&[_]u8{
+ \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header
+ \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs
+ \\ DW.AT_low_pc, DW_FORM_addr,
+ \\ DW.AT_high_pc, DW_FORM_addr,
+ \\ DW.AT_name, DW_FORM_strp,
+ \\ DW.AT_comp_dir, DW_FORM_strp,
+ \\ DW.AT_producer, DW_FORM_strp,
+ \\ DW.AT_language, DW_FORM_data2,
+ \\ 0, 0, // sentinel
+ \\ });
+ \\
+ \\ self.code.appendSliceAssumeCapacity(&[_]u8{
+ \\ 0x55, // push rbp
+ \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
+ \\ // How do we handle this?
+ \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
+ \\ // Here's a blank line, should that be allowed?
+ \\
+ \\ 0x48, 0x89, 0xe5,
+ \\ 0x33, 0x45,
+ \\ // Now the comment breaks a single line -- how do we handle this?
+ \\ 0x88,
+ \\ });
\\}
\\
);
}
-test "zig fmt: multiline string in array" {
+test "zig fmt: multiline string literals should play nice with array initializers" {
try testCanonical(
- \\const Foo = [][]const u8{
- \\ \\aaa
- \\ ,
- \\ \\bbb
- \\};
- \\
- \\fn bar() void {
- \\ const Foo = [][]const u8{
- \\ \\aaa
+ \\fn main() void {
+ \\ var a = .{.{.{.{.{.{.{.{
+ \\ 0,
+ \\ }}}}}}}};
+ \\ myFunc(.{
+ \\ "aaaaaaa", "bbbbbb", "ccccc",
+ \\ "dddd", ("eee"), ("fff"),
+ \\ ("gggg"),
+ \\ // Line comment
+ \\ \\Multiline String Literals can be quite long
\\ ,
- \\ \\bbb
- \\ };
- \\ const Bar = [][]const u8{ // comment here
- \\ \\aaa
- \\ \\
- \\ , // and another comment can go here
- \\ \\bbb
- \\ };
+ \\ \\Multiline String Literals can be quite long
+ \\ \\Multiline String Literals can be quite long
+ \\ ,
+ \\ \\Multiline String Literals can be quite long
+ \\ \\Multiline String Literals can be quite long
+ \\ \\Multiline String Literals can be quite long
+ \\ \\Multiline String Literals can be quite long
+ \\ ,
+ \\ (
+ \\ \\Multiline String Literals can be quite long
+ \\ ),
+ \\ .{
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ },
+ \\ .{(
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ )},
+ \\ .{
+ \\ "xxxxxxx", "xxx",
+ \\ (
+ \\ \\ xxx
+ \\ ),
+ \\ "xxx",
+ \\ "xxx",
+ \\ },
+ \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" },
+ \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" },
+ \\ "aaaaaaa", "bbbbbb", "ccccc", // -
+ \\ "dddd", ("eee"), ("fff"),
+ \\ .{
+ \\ "xxx", "xxx",
+ \\ (
+ \\ \\ xxx
+ \\ ),
+ \\ "xxxxxxxxxxxxxx",
+ \\ "xxx",
+ \\ },
+ \\ .{
+ \\ (
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ ),
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ },
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ \\ });
\\}
\\
);
}
-test "zig fmt: file ends with struct field" {
+test "zig fmt: use of comments and multiline string literals may force the parameters over multiple lines" {
try testCanonical(
- \\a: bool
+ \\pub fn makeMemUndefined(qzz: []u8) i1 {
+ \\ cases.add( // fixed bug foo
+ \\ "compile diagnostic string for top level decl type",
+ \\ \\export fn entry() void {
+ \\ \\ var foo: u32 = @This(){};
+ \\ \\}
+ \\ , &[_][]const u8{
+ \\ "tmp.zig:2:27: error: type 'u32' does not support array initialization",
+ \\ });
+ \\ @compileError(
+ \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
+ \\ \\ Consider providing your own hash function.
+ \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
+ \\ \\ Consider providing your own hash function.
+ \\ );
+ \\ return @intCast(doMemCheckClientRequestExpr(0, // default return
+ \\ .MakeMemUndefined, @intFromPtr(qzz.ptr), qzz.len, 0, 0, 0));
+ \\}
+ \\
+ \\// This looks like garbage don't do this
+ \\const rparen = tree.prevToken(
+ \\ // the first token for the annotation expressions is the left
+ \\ // parenthesis, hence the need for two prevToken
+ \\ if (fn_proto.getAlignExpr()) |align_expr|
+ \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))
+ \\ else if (fn_proto.getSectionExpr()) |section_expr|
+ \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))
+ \\ else if (fn_proto.getCallconvExpr()) |callconv_expr|
+ \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
+ \\ else switch (fn_proto.return_type) {
+ \\ .Explicit => |node| node.firstToken(),
+ \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),
+ \\ .Invalid => unreachable,
+ \\ });
\\
);
}
-test "zig fmt: comment after empty comment" {
+test "zig fmt: single argument trailing commas in @builtins()" {
try testCanonical(
- \\//
- \\/// A doc comment
- \\const a = b;
+ \\pub fn foo(qzz: []u8) i1 {
+ \\ @panic(
+ \\ foo,
+ \\ );
+ \\ panic(
+ \\ foo,
+ \\ );
+ \\ @panic(
+ \\ foo,
+ \\ bar,
+ \\ );
+ \\}
\\
);
}
-test "zig fmt: line comment in array" {
+test "zig fmt: trailing comma should force multiline 1 column" {
try testTransform(
- \\test "a" {
- \\ var arr = [_]u32{
- \\ 0
- \\ // 1,
- \\ // 2,
- \\ };
- \\}
+ \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
\\
,
- \\test "a" {
- \\ var arr = [_]u32{
- \\ 0,
- \\ // 1,
- \\ // 2,
- \\ };
- \\}
+ \\pub const UUID_NULL: uuid_t = [16]u8{
+ \\ 0,
+ \\ 0,
+ \\ 0,
+ \\ 0,
+ \\};
\\
);
+}
+
+test "zig fmt: function params should align nicely" {
try testCanonical(
- \\test "a" {
- \\ var arr = [_]u32{
- \\ 0,
- \\ // 1,
- \\ // 2,
- \\ };
+ \\pub fn foo() void {
+ \\ cases.addRuntimeSafety("slicing operator with sentinel",
+ \\ \\const std = @import("std");
+ \\ ++ check_panic_msg ++
+ \\ \\pub fn main() void {
+ \\ \\ var buf = [4]u8{'a','b','c',0};
+ \\ \\ const slice = buf[0..:0];
+ \\ \\}
+ \\ );
\\}
\\
);
}
-test "zig fmt: comment after params" {
+test "zig fmt: fn proto end with anytype and comma" {
try testCanonical(
- \\fn foo(
- \\ a: i32, // comment
- \\ b: i32, // comment
- \\) void {}
+ \\pub fn format(
+ \\ out_stream: anytype,
+ \\) !void {}
\\
);
}
-test "zig fmt: comment in array initializer/access" {
+test "zig fmt: space after top level doc comment" {
try testCanonical(
- \\test "a" {
- \\ var a = x{ //aa
- \\ //bb
- \\ };
- \\ var a = []x{ //aa
- \\ //bb
- \\ };
- \\ var b = [ //aa
- \\ _
- \\ ]x{ //aa
- \\ //bb
- \\ 9,
- \\ };
- \\ var c = b[ //aa
- \\ 0
- \\ ];
- \\ var d = [
- \\ _
- \\ //aa
- \\ :
- \\ 0
- \\ ]x{ //aa
- \\ //bb
- \\ 9,
- \\ };
- \\ var e = d[
- \\ 0
- \\ //aa
- \\ ];
- \\}
+ \\//! top level doc comment
+ \\
+ \\field: i32,
\\
);
}
-test "zig fmt: comments at several places in struct init" {
+test "zig fmt: remove trailing whitespace after container doc comment" {
try testTransform(
- \\var bar = Bar{
- \\ .x = 10, // test
- \\ .y = "test"
- \\ // test
- \\};
+ \\//! top level doc comment
\\
,
- \\var bar = Bar{
- \\ .x = 10, // test
- \\ .y = "test",
- \\ // test
- \\};
- \\
- );
-
- try testCanonical(
- \\var bar = Bar{ // test
- \\ .x = 10, // test
- \\ .y = "test",
- \\ // test
- \\};
- \\
- );
-}
-
-test "zig fmt: container doc comments" {
- try testCanonical(
- \\//! tld 1
- \\//! tld 2
- \\//! tld 3
- \\const a = b;
+ \\//! top level doc comment
\\
);
}
-test "zig fmt: remove newlines surrounding doc comment" {
+test "zig fmt: remove trailing whitespace after doc comment" {
try testTransform(
- \\
- \\
- \\
- \\/// doc comment
- \\
- \\fn foo() void {}
+ \\/// doc comment
+ \\a = 0,
\\
,
\\/// doc comment
- \\fn foo() void {}
+ \\a = 0,
\\
);
}
-test "zig fmt: remove newlines surrounding doc comment between members" {
- try testTransform(
- \\f1: i32,
- \\
- \\
- \\/// doc comment
- \\
- \\f2: i32,
- \\
- ,
- \\f1: i32,
- \\
- \\/// doc comment
- \\f2: i32,
+test "zig fmt: for loop with ptr payload and index" {
+ try testCanonical(
+ \\test {
+ \\ for (self.entries.items, 0..) |*item, i| {}
+ \\ for (self.entries.items, 0..) |*item, i|
+ \\ a = b;
+ \\ for (self.entries.items, 0..) |*item, i| a = b;
+ \\}
\\
);
}
-test "zig fmt: remove newlines surrounding doc comment between members within container decl (1)" {
- try testTransform(
- \\const Foo = struct {
- \\ fn foo() void {}
- \\
- \\
- \\ /// doc comment
- \\
- \\
- \\ fn bar() void {}
- \\};
- \\
- ,
- \\const Foo = struct {
- \\ fn foo() void {}
+test "zig fmt: proper indent line comment after multi-line single expr while loop" {
+ try testCanonical(
+ \\test {
+ \\ while (a) : (b)
+ \\ foo();
\\
- \\ /// doc comment
- \\ fn bar() void {}
- \\};
+ \\ // bar
+ \\ baz();
+ \\}
\\
);
}
-test "zig fmt: remove newlines surrounding doc comment between members within container decl (2)" {
- try testTransform(
- \\const Foo = struct {
- \\ fn foo() void {}
- \\ /// doc comment 1
- \\
- \\ /// doc comment 2
- \\
- \\ fn bar() void {}
- \\};
- \\
- ,
- \\const Foo = struct {
- \\ fn foo() void {}
- \\ /// doc comment 1
- \\ /// doc comment 2
- \\ fn bar() void {}
- \\};
+test "zig fmt: extern function with missing param name" {
+ try testCanonical(
+ \\extern fn a(
+ \\ *b,
+ \\ c: *d,
+ \\) e;
+ \\extern fn f(*g, h: *i) j;
\\
);
}
-test "zig fmt: remove newlines surrounding doc comment within container decl" {
- try testTransform(
- \\const Foo = struct {
- \\
- \\
- \\ /// doc comment
- \\
- \\ fn foo() void {}
- \\};
+test "zig fmt: respect extra newline between switch items" {
+ try testCanonical(
+ \\const a = switch (b) {
+ \\ .c => {},
\\
- ,
- \\const Foo = struct {
- \\ /// doc comment
- \\ fn foo() void {}
+ \\ .d,
+ \\ .e,
+ \\ => f,
\\};
\\
);
}
-test "zig fmt: comments with CRLF line endings" {
- try testTransform("" ++
- "//! Top-level doc comment\r\n" ++
- "//! Continuing to another line\r\n" ++
- "\r\n" ++
- "/// Regular doc comment\r\n" ++
- "const S = struct {\r\n" ++
- " // Regular comment\r\n" ++
- " // More content\r\n" ++
- "};\r\n",
- \\//! Top-level doc comment
- \\//! Continuing to another line
- \\
- \\/// Regular doc comment
- \\const S = struct {
- \\ // Regular comment
- \\ // More content
- \\};
+test "zig fmt: assignment with inline for and inline while" {
+ try testCanonical(
+ \\const tmp = inline for (items) |item| {};
\\
);
-}
-test "zig fmt: else comptime expr" {
try testCanonical(
- \\comptime {
- \\ if (true) {} else comptime foo();
- \\}
- \\comptime {
- \\ while (true) {} else comptime foo();
- \\}
- \\comptime {
- \\ for ("") |_| {} else comptime foo();
- \\}
+ \\const tmp2 = inline while (true) {};
\\
);
}
-test "zig fmt: integer literals with underscore separators" {
- try testTransform(
- \\const
- \\ x =
- \\ 1_234_567
- \\ + (0b0_1-0o7_0+0xff_FF ) + 1_0;
- ,
- \\const x =
- \\ 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 1_0;
+test "zig fmt: saturating arithmetic" {
+ try testCanonical(
+ \\test {
+ \\ const actual = switch (op) {
+ \\ .add => a +| b,
+ \\ .sub => a -| b,
+ \\ .mul => a *| b,
+ \\ .shl => a <<| b,
+ \\ };
+ \\ switch (op) {
+ \\ .add => actual +|= b,
+ \\ .sub => actual -|= b,
+ \\ .mul => actual *|= b,
+ \\ .shl => actual <<|= b,
+ \\ }
+ \\}
\\
);
}
-test "zig fmt: hex literals with underscore separators" {
+test "zig fmt: insert trailing comma if there are comments between switch values" {
try testTransform(
- \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
- \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
- \\ for (c [ 1_0 .. ], 0..) |_, i| {
- \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
- \\ }
- \\ return c;
- \\}
+ \\const a = switch (b) {
+ \\ .c => {},
+ \\
+ \\ .d, // foobar
+ \\ .e
+ \\ => f,
\\
+ \\ .g, .h
+ \\ // comment
+ \\ => i,
+ \\};
\\
,
- \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
- \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
- \\ for (c[1_0..], 0..) |_, i| {
- \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
- \\ }
- \\ return c;
- \\}
+ \\const a = switch (b) {
+ \\ .c => {},
+ \\
+ \\ .d, // foobar
+ \\ .e,
+ \\ => f,
+ \\
+ \\ .g,
+ \\ .h,
+ \\ // comment
+ \\ => i,
+ \\};
\\
);
}
-test "zig fmt: decimal float literals with underscore separators" {
- try testCanonical(
- \\const x = 1_234_567.89_10_11;
- \\const y = 1_234_567.89_10_11e1_213_14;
- \\const z = 1_234_567;
+test "zig fmt: insert trailing comma if comments in array init" {
+ try testTransform(
+ \\var a = .{
+ \\ "foo", //
+ \\ "bar"
+ \\};
+ \\var a = .{
+ \\ "foo",
+ \\ "bar" //
+ \\};
+ \\var a = .{
+ \\ "foo",
+ \\ "//"
+ \\};
+ \\var a = .{
+ \\ "foo",
+ \\ "//" //
+ \\};
+ \\
+ ,
+ \\var a = .{
+ \\ "foo", //
+ \\ "bar",
+ \\};
+ \\var a = .{
+ \\ "foo",
+ \\ "bar", //
+ \\};
+ \\var a = .{ "foo", "//" };
+ \\var a = .{
+ \\ "foo",
+ \\ "//", //
+ \\};
\\
);
}
-test "zig fmt: hexadecimal float literals with underscore separators" {
+test "zig fmt: make single-line if no trailing comma" {
try testTransform(
- \\pub fn main() void {
- \\ const a: f64 = (0x10.0p-0+(0x10.0p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
- \\ const b: f64 = 0x0010.0--0x00_10.0+0x10.00+0x1p4;
- \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
+ \\test "function call no trailing comma" {
+ \\ foo(
+ \\ 1,
+ \\ 2
+ \\ );
\\}
+ \\
,
- \\pub fn main() void {
- \\ const a: f64 = (0x10.0p-0 + (0x10.0p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
- \\ const b: f64 = 0x0010.0 - -0x00_10.0 + 0x10.00 + 0x1p4;
- \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
+ \\test "function call no trailing comma" {
+ \\ foo(1, 2);
\\}
\\
);
-}
-test "zig fmt: C var args" {
- try testCanonical(
- \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
+ try testTransform(
+ \\test "struct no trailing comma" {
+ \\ const a = .{
+ \\ .foo = 1,
+ \\ .bar = 2
+ \\ };
+ \\}
\\
- );
-}
-
-test "zig fmt: Only indent multiline string literals in function calls" {
- try testCanonical(
- \\test "zig fmt:" {
- \\ try testTransform(
- \\ \\const X = struct {
- \\ \\ foo: i32, bar: i8 };
- \\ ,
- \\ \\const X = struct {
- \\ \\ foo: i32, bar: i8
- \\ \\};
- \\ \\
- \\ );
+ ,
+ \\test "struct no trailing comma" {
+ \\ const a = .{ .foo = 1, .bar = 2 };
\\}
\\
);
-}
-test "zig fmt: Don't add extra newline after if" {
- try testCanonical(
- \\pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void {
- \\ if (cwd().symLink(existing_path, new_path, .{})) {
- \\ return;
- \\ }
+ try testTransform(
+ \\test "array no trailing comma" {
+ \\ var stream = multiOutStream(.{
+ \\ fbs1.outStream(),
+ \\ fbs2.outStream()
+ \\ });
+ \\}
+ \\
+ ,
+ \\test "array no trailing comma" {
+ \\ var stream = multiOutStream(.{ fbs1.outStream(), fbs2.outStream() });
\\}
\\
);
}
-test "zig fmt: comments in ternary ifs" {
- try testCanonical(
- \\const x = if (true) {
- \\ 1;
- \\} else if (false)
- \\ // Comment
- \\ 0;
- \\const y = if (true)
- \\ // Comment
- \\ 1
- \\else
- \\ // Comment
- \\ 0;
+test "zig fmt: preserve container doc comment in container without trailing comma" {
+ try testTransform(
+ \\const A = enum(u32) {
+ \\//! comment
+ \\_ };
\\
- \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
+ ,
+ \\const A = enum(u32) {
+ \\ //! comment
+ \\ _,
+ \\};
\\
);
}
-test "zig fmt: while statement in blockless if" {
- try testCanonical(
- \\pub fn main() void {
- \\ const zoom_node = if (focused_node == layout_first)
- \\ while (it.next()) |node| {
- \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
- \\ } else null
- \\ else
- \\ focused_node;
+test "zig fmt: no space before newline before multiline string" {
+ try testCanonical(
+ \\const S = struct {
+ \\ text: []const u8,
+ \\ comment: []const u8,
+ \\};
+ \\
+ \\test {
+ \\ const s1 = .{
+ \\ .text =
+ \\ \\hello
+ \\ \\world
+ \\ ,
+ \\ .comment = "test",
+ \\ };
+ \\ _ = s1;
+ \\ const s2 = .{
+ \\ .comment = "test",
+ \\ .text =
+ \\ \\hello
+ \\ \\world
+ \\ ,
+ \\ };
+ \\ _ = s2;
\\}
\\
);
}
-test "zig fmt: test comments in field access chain" {
- try testCanonical(
- \\pub const str = struct {
- \\ pub const Thing = more.more //
- \\ .more() //
- \\ .more().more() //
- \\ .more() //
- \\ // .more() //
- \\ .more() //
- \\ .more();
- \\ data: Data,
+test "zig fmt: don't canonicalize _ in enums" {
+ try testTransform(
+ \\const A = enum {
+ \\ first,
+ \\ second,
+ \\ third,
+ \\ _,
\\};
- \\
- \\pub const str = struct {
- \\ pub const Thing = more.more //
- \\ .more() //
- \\ // .more() //
- \\ // .more() //
- \\ // .more() //
- \\ .more() //
- \\ .more();
- \\ data: Data,
+ \\const B = enum {
+ \\ @"_",
+ \\ @"__",
+ \\ @"___",
+ \\ @"____",
+ \\};
+ \\const C = struct {
+ \\ @"_": u8,
+ \\ @"__": u8,
+ \\ @"___": u8,
+ \\ @"____": u8,
+ \\};
+ \\const D = union {
+ \\ @"_": u8,
+ \\ @"__": u8,
+ \\ @"___": u8,
+ \\ @"____": u8,
\\};
\\
- \\pub const str = struct {
- \\ pub const Thing = more //
- \\ .more //
- \\ .more() //
- \\ .more();
- \\ data: Data,
+ ,
+ \\const A = enum {
+ \\ first,
+ \\ second,
+ \\ third,
+ \\ _,
+ \\};
+ \\const B = enum {
+ \\ @"_",
+ \\ __,
+ \\ ___,
+ \\ ____,
+ \\};
+ \\const C = struct {
+ \\ _: u8,
+ \\ __: u8,
+ \\ ___: u8,
+ \\ ____: u8,
+ \\};
+ \\const D = union {
+ \\ _: u8,
+ \\ __: u8,
+ \\ ___: u8,
+ \\ ____: u8,
\\};
\\
);
}
-test "zig fmt: allow line break before field access" {
+test "zig fmt: pointer type syntax to index" {
try testCanonical(
\\test {
- \\ const w = foo.bar().zippy(zag).iguessthisisok();
- \\
- \\ const x = foo
- \\ .bar()
- \\ . // comment
- \\ // comment
- \\ swooop().zippy(zag)
- \\ .iguessthisisok();
- \\
- \\ const y = view.output.root.server.input_manager.default_seat.wlr_seat.name;
- \\
- \\ const z = view.output.root.server
- \\ .input_manager //
- \\ .default_seat
- \\ . // comment
- \\ // another comment
- \\ wlr_seat.name;
+ \\ _ = .{}[*0];
\\}
\\
);
- try testTransform(
- \\test {
- \\ const x = foo.
- \\ bar()
- \\ .zippy(zag).iguessthisisok();
- \\
- \\ const z = view.output.root.server.
- \\ input_manager.
- \\ default_seat.wlr_seat.name;
- \\}
- \\
- ,
+}
+
+test "zig fmt: binop indentation in if statement" {
+ try testCanonical(
\\test {
- \\ const x = foo
- \\ .bar()
- \\ .zippy(zag).iguessthisisok();
- \\
- \\ const z = view.output.root.server
- \\ .input_manager
- \\ .default_seat.wlr_seat.name;
+ \\ if (first_param_type.isGenericPoison() or
+ \\ (first_param_type.zigTypeTag(zcu) == .pointer and
+ \\ (first_param_type.ptrSize(zcu) == .One or
+ \\ first_param_type.ptrSize(zcu) == .C) and
+ \\ first_param_type.childType(zcu).eql(concrete_ty, zcu)))
+ \\ {
+ \\ f(x);
+ \\ }
\\}
\\
);
}
-test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
+test "zig fmt: test indentation of if expressions" {
try testCanonical(
- \\fn foo() void {
- \\ z.display_message_dialog(
- \\ *const [323:0]u8,
- \\ \\Message Text
- \\ \\------------
- \\ \\xxxxxxxxxxxx
- \\ \\xxxxxxxxxxxx
- \\ ,
- \\ g.GtkMessageType.GTK_MESSAGE_WARNING,
- \\ null,
- \\ );
+ \\test {
+ \\ const foo = 1 +
+ \\ if (1 == 2)
+ \\ 2
+ \\ else
+ \\ 0;
\\
- \\ z.display_message_dialog(*const [323:0]u8,
- \\ \\Message Text
- \\ \\------------
- \\ \\xxxxxxxxxxxx
- \\ \\xxxxxxxxxxxx
- \\ , g.GtkMessageType.GTK_MESSAGE_WARNING, null);
+ \\ const foo = 1 + if (1 == 2)
+ \\ 2
+ \\ else
+ \\ 0;
+ \\
+ \\ errval catch |e|
+ \\ if (e == error.Meow)
+ \\ return 0x1F408
+ \\ else
+ \\ unreachable;
+ \\
+ \\ errval catch |e| if (e == error.Meow)
+ \\ return 0x1F408
+ \\ else
+ \\ unreachable;
+ \\
+ \\ return if (1 == 2)
+ \\ 1
+ \\ else if (3 > 4)
+ \\ 2
+ \\ else
+ \\ 0;
\\}
\\
);
}
+test "Ast header smoke test" {
+ try std.testing.expectEqual(zigNode(c.AST_NODE_IF), Ast.Node.Tag.@"if");
+}
+
+var fixed_buffer_mem: [100 * 1024]u8 = undefined;
+
+fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
+ var stderr_buf: [4096]u8 = undefined;
+ var stderr_file_writer = std.fs.File.stderr().writer(&stderr_buf);
+ const stderr = &stderr_file_writer.interface;
+
+ //var tree = try std.zig.Ast.parse(allocator, source, .zig);
+ var c_tree = c.astParse(source, @intCast(source.len));
+ defer c.astDeinit(&c_tree);
+ var tree = try zigAst(allocator, c_tree);
+ defer tree.deinit(allocator);
+
+ for (tree.errors) |parse_error| {
+ const loc = tree.tokenLocation(0, parse_error.token);
+ try stderr.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 });
+ try tree.renderError(parse_error, stderr);
+ try stderr.print("\n{s}\n", .{source[loc.line_start..loc.line_end]});
+ {
+ var i: usize = 0;
+ while (i < loc.column) : (i += 1) {
+ try stderr.writeAll(" ");
+ }
+ try stderr.writeAll("^");
+ }
+ try stderr.writeAll("\n");
+ }
+ if (tree.errors.len != 0) {
+ return error.ParseError;
+ }
+
+ const formatted = try tree.renderAlloc(allocator);
+ anything_changed.* = !mem.eql(u8, formatted, source);
+ return formatted;
+}
+fn testTransformImpl(allocator: mem.Allocator, fba: *std.heap.FixedBufferAllocator, source: [:0]const u8, expected_source: []const u8) !void {
+ // reset the fixed buffer allocator each run so that it can be re-used for each
+ // iteration of the failing index
+ fba.reset();
+ var anything_changed: bool = undefined;
+ const result_source = try testParse(source, allocator, &anything_changed);
+ try std.testing.expectEqualStrings(expected_source, result_source);
+ const changes_expected = source.ptr != expected_source.ptr;
+ if (anything_changed != changes_expected) {
+ print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected });
+ return error.TestFailed;
+ }
+ try std.testing.expect(anything_changed == changes_expected);
+ allocator.free(result_source);
+}
+fn testTransform(source: [:0]const u8, expected_source: []const u8) !void {
+ var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
+ return std.testing.checkAllAllocationFailures(fixed_allocator.allocator(), testTransformImpl, .{ &fixed_allocator, source, expected_source });
+}
+fn testCanonical(source: [:0]const u8) !void {
+ return testTransform(source, source);
+}
+
+const Error = std.zig.Ast.Error.Tag;
-test "zig fmt: regression test for #5722" {
- try testCanonical(
- \\pub fn sendViewTags(self: Self) void {
- \\ var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));
- \\ while (it.next()) |node|
- \\ view_tags.append(node.view.current_tags) catch {
- \\ c.wl_resource_post_no_memory(self.wl_resource);
- \\ log.err(.river_status, "out of memory", .{});
- \\ return;
- \\ };
- \\}
- \\
- );
-}
+fn testError(source: [:0]const u8, expected_errors: []const Error) !void {
+ var tree = try std.zig.Ast.parse(std.testing.allocator, source, .zig);
+ defer tree.deinit(std.testing.allocator);
-test "zig fmt: regression test for #8974" {
- try testCanonical(
- \\pub const VARIABLE;
- \\
- );
+ std.testing.expectEqual(expected_errors.len, tree.errors.len) catch |err| {
+ std.debug.print("errors found: {any}\n", .{tree.errors});
+ return err;
+ };
+ for (expected_errors, 0..) |expected, i| {
+ try std.testing.expectEqual(expected, tree.errors[i].tag);
+ }
}
-test "zig fmt: allow trailing line comments to do manual array formatting" {
- try testCanonical(
- \\fn foo() void {
- \\ self.code.appendSliceAssumeCapacity(&[_]u8{
- \\ 0x55, // push rbp
- \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
- \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
- \\ });
- \\
- \\ di_buf.appendAssumeCapacity(&[_]u8{
- \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header
- \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs
- \\ DW.AT_low_pc, DW_FORM_addr,
- \\ DW.AT_high_pc, DW_FORM_addr,
- \\ DW.AT_name, DW_FORM_strp,
- \\ DW.AT_comp_dir, DW_FORM_strp,
- \\ DW.AT_producer, DW_FORM_strp,
- \\ DW.AT_language, DW_FORM_data2,
- \\ 0, 0, // sentinel
- \\ });
- \\
- \\ self.code.appendSliceAssumeCapacity(&[_]u8{
- \\ 0x55, // push rbp
- \\ 0x48, 0x89, 0xe5, // mov rbp, rsp
- \\ // How do we handle this?
- \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
- \\ // Here's a blank line, should that be allowed?
- \\
- \\ 0x48, 0x89, 0xe5,
- \\ 0x33, 0x45,
- \\ // Now the comment breaks a single line -- how do we handle this?
- \\ 0x88,
- \\ });
- \\}
- \\
- );
-}
+const testing = std.testing;
-test "zig fmt: multiline string literals should play nice with array initializers" {
- try testCanonical(
- \\fn main() void {
- \\ var a = .{.{.{.{.{.{.{.{
- \\ 0,
- \\ }}}}}}}};
- \\ myFunc(.{
- \\ "aaaaaaa", "bbbbbb", "ccccc",
- \\ "dddd", ("eee"), ("fff"),
- \\ ("gggg"),
- \\ // Line comment
- \\ \\Multiline String Literals can be quite long
- \\ ,
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ ,
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ \\Multiline String Literals can be quite long
- \\ ,
- \\ (
- \\ \\Multiline String Literals can be quite long
- \\ ),
- \\ .{
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ },
- \\ .{(
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ )},
- \\ .{
- \\ "xxxxxxx", "xxx",
- \\ (
- \\ \\ xxx
- \\ ),
- \\ "xxx",
- \\ "xxx",
- \\ },
- \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" },
- \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" },
- \\ "aaaaaaa", "bbbbbb", "ccccc", // -
- \\ "dddd", ("eee"), ("fff"),
- \\ .{
- \\ "xxx", "xxx",
- \\ (
- \\ \\ xxx
- \\ ),
- \\ "xxxxxxxxxxxxxx",
- \\ "xxx",
- \\ },
- \\ .{
- \\ (
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ ),
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ },
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- \\ });
- \\}
- \\
- );
+const Ast = std.zig.Ast;
+const Allocator = std.mem.Allocator;
+
+const c = @cImport({
+ @cInclude("ast.h");
+});
+
+const zigToken = @import("./tokenizer_test.zig").zigToken;
+
+fn zigNode(token: c_uint) Ast.Node.Tag {
+ return switch (token) {
+ c.AST_NODE_ROOT => .root,
+ c.AST_NODE_TEST_DECL => .test_decl,
+ c.AST_NODE_GLOBAL_VAR_DECL => .global_var_decl,
+ c.AST_NODE_LOCAL_VAR_DECL => .local_var_decl,
+ c.AST_NODE_SIMPLE_VAR_DECL => .simple_var_decl,
+ c.AST_NODE_ALIGNED_VAR_DECL => .aligned_var_decl,
+ c.AST_NODE_ERRDEFER => .@"errdefer",
+ c.AST_NODE_DEFER => .@"defer",
+ c.AST_NODE_CATCH => .@"catch",
+ c.AST_NODE_FIELD_ACCESS => .field_access,
+ c.AST_NODE_UNWRAP_OPTIONAL => .unwrap_optional,
+ c.AST_NODE_EQUAL_EQUAL => .equal_equal,
+ c.AST_NODE_BANG_EQUAL => .bang_equal,
+ c.AST_NODE_LESS_THAN => .less_than,
+ c.AST_NODE_GREATER_THAN => .greater_than,
+ c.AST_NODE_LESS_OR_EQUAL => .less_or_equal,
+ c.AST_NODE_GREATER_OR_EQUAL => .greater_or_equal,
+ c.AST_NODE_ASSIGN_MUL => .assign_mul,
+ c.AST_NODE_ASSIGN_DIV => .assign_div,
+ c.AST_NODE_ASSIGN_MOD => .assign_mod,
+ c.AST_NODE_ASSIGN_ADD => .assign_add,
+ c.AST_NODE_ASSIGN_SUB => .assign_sub,
+ c.AST_NODE_ASSIGN_SHL => .assign_shl,
+ c.AST_NODE_ASSIGN_SHL_SAT => .assign_shl_sat,
+ c.AST_NODE_ASSIGN_SHR => .assign_shr,
+ c.AST_NODE_ASSIGN_BIT_AND => .assign_bit_and,
+ c.AST_NODE_ASSIGN_BIT_XOR => .assign_bit_xor,
+ c.AST_NODE_ASSIGN_BIT_OR => .assign_bit_or,
+ c.AST_NODE_ASSIGN_MUL_WRAP => .assign_mul_wrap,
+ c.AST_NODE_ASSIGN_ADD_WRAP => .assign_add_wrap,
+ c.AST_NODE_ASSIGN_SUB_WRAP => .assign_sub_wrap,
+ c.AST_NODE_ASSIGN_MUL_SAT => .assign_mul_sat,
+ c.AST_NODE_ASSIGN_ADD_SAT => .assign_add_sat,
+ c.AST_NODE_ASSIGN_SUB_SAT => .assign_sub_sat,
+ c.AST_NODE_ASSIGN => .assign,
+ c.AST_NODE_ASSIGN_DESTRUCTURE => .assign_destructure,
+ c.AST_NODE_MERGE_ERROR_SETS => .merge_error_sets,
+ c.AST_NODE_MUL => .mul,
+ c.AST_NODE_DIV => .div,
+ c.AST_NODE_MOD => .mod,
+ c.AST_NODE_ARRAY_MULT => .array_mult,
+ c.AST_NODE_MUL_WRAP => .mul_wrap,
+ c.AST_NODE_MUL_SAT => .mul_sat,
+ c.AST_NODE_ADD => .add,
+ c.AST_NODE_SUB => .sub,
+ c.AST_NODE_ARRAY_CAT => .array_cat,
+ c.AST_NODE_ADD_WRAP => .add_wrap,
+ c.AST_NODE_SUB_WRAP => .sub_wrap,
+ c.AST_NODE_ADD_SAT => .add_sat,
+ c.AST_NODE_SUB_SAT => .sub_sat,
+ c.AST_NODE_SHL => .shl,
+ c.AST_NODE_SHL_SAT => .shl_sat,
+ c.AST_NODE_SHR => .shr,
+ c.AST_NODE_BIT_AND => .bit_and,
+ c.AST_NODE_BIT_XOR => .bit_xor,
+ c.AST_NODE_BIT_OR => .bit_or,
+ c.AST_NODE_ORELSE => .@"orelse",
+ c.AST_NODE_BOOL_AND => .bool_and,
+ c.AST_NODE_BOOL_OR => .bool_or,
+ c.AST_NODE_BOOL_NOT => .bool_not,
+ c.AST_NODE_NEGATION => .negation,
+ c.AST_NODE_BIT_NOT => .bit_not,
+ c.AST_NODE_NEGATION_WRAP => .negation_wrap,
+ c.AST_NODE_ADDRESS_OF => .address_of,
+ c.AST_NODE_TRY => .@"try",
+ c.AST_NODE_OPTIONAL_TYPE => .optional_type,
+ c.AST_NODE_ARRAY_TYPE => .array_type,
+ c.AST_NODE_ARRAY_TYPE_SENTINEL => .array_type_sentinel,
+ c.AST_NODE_PTR_TYPE_ALIGNED => .ptr_type_aligned,
+ c.AST_NODE_PTR_TYPE_SENTINEL => .ptr_type_sentinel,
+ c.AST_NODE_PTR_TYPE => .ptr_type,
+ c.AST_NODE_PTR_TYPE_BIT_RANGE => .ptr_type_bit_range,
+ c.AST_NODE_SLICE_OPEN => .slice_open,
+ c.AST_NODE_SLICE => .slice,
+ c.AST_NODE_SLICE_SENTINEL => .slice_sentinel,
+ c.AST_NODE_DEREF => .deref,
+ c.AST_NODE_ARRAY_ACCESS => .array_access,
+ c.AST_NODE_ARRAY_INIT_ONE => .array_init_one,
+ c.AST_NODE_ARRAY_INIT_ONE_COMMA => .array_init_one_comma,
+ c.AST_NODE_ARRAY_INIT_DOT_TWO => .array_init_dot_two,
+ c.AST_NODE_ARRAY_INIT_DOT_TWO_COMMA => .array_init_dot_two_comma,
+ c.AST_NODE_ARRAY_INIT_DOT => .array_init_dot,
+ c.AST_NODE_ARRAY_INIT_DOT_COMMA => .array_init_dot_comma,
+ c.AST_NODE_ARRAY_INIT => .array_init,
+ c.AST_NODE_ARRAY_INIT_COMMA => .array_init_comma,
+ c.AST_NODE_STRUCT_INIT_ONE => .struct_init_one,
+ c.AST_NODE_STRUCT_INIT_ONE_COMMA => .struct_init_one_comma,
+ c.AST_NODE_STRUCT_INIT_DOT_TWO => .struct_init_dot_two,
+ c.AST_NODE_STRUCT_INIT_DOT_TWO_COMMA => .struct_init_dot_two_comma,
+ c.AST_NODE_STRUCT_INIT_DOT => .struct_init_dot,
+ c.AST_NODE_STRUCT_INIT_DOT_COMMA => .struct_init_dot_comma,
+ c.AST_NODE_STRUCT_INIT => .struct_init,
+ c.AST_NODE_STRUCT_INIT_COMMA => .struct_init_comma,
+ c.AST_NODE_CALL_ONE => .call_one,
+ c.AST_NODE_CALL_ONE_COMMA => .call_one_comma,
+ c.AST_NODE_CALL => .call,
+ c.AST_NODE_CALL_COMMA => .call_comma,
+ c.AST_NODE_SWITCH => .@"switch",
+ c.AST_NODE_SWITCH_COMMA => .switch_comma,
+ c.AST_NODE_SWITCH_CASE_ONE => .switch_case_one,
+ c.AST_NODE_SWITCH_CASE_INLINE_ONE => .switch_case_inline_one,
+ c.AST_NODE_SWITCH_CASE => .switch_case,
+ c.AST_NODE_SWITCH_CASE_INLINE => .switch_case_inline,
+ c.AST_NODE_SWITCH_RANGE => .switch_range,
+ c.AST_NODE_WHILE_SIMPLE => .while_simple,
+ c.AST_NODE_WHILE_CONT => .while_cont,
+ c.AST_NODE_WHILE => .@"while",
+ c.AST_NODE_FOR_SIMPLE => .for_simple,
+ c.AST_NODE_FOR => .@"for",
+ c.AST_NODE_FOR_RANGE => .for_range,
+ c.AST_NODE_IF_SIMPLE => .if_simple,
+ c.AST_NODE_IF => .@"if",
+ c.AST_NODE_SUSPEND => .@"suspend",
+ c.AST_NODE_RESUME => .@"resume",
+ c.AST_NODE_CONTINUE => .@"continue",
+ c.AST_NODE_BREAK => .@"break",
+ c.AST_NODE_RETURN => .@"return",
+ c.AST_NODE_FN_PROTO_SIMPLE => .fn_proto_simple,
+ c.AST_NODE_FN_PROTO_MULTI => .fn_proto_multi,
+ c.AST_NODE_FN_PROTO_ONE => .fn_proto_one,
+ c.AST_NODE_FN_PROTO => .fn_proto,
+ c.AST_NODE_FN_DECL => .fn_decl,
+ c.AST_NODE_ANYFRAME_TYPE => .anyframe_type,
+ c.AST_NODE_ANYFRAME_LITERAL => .anyframe_literal,
+ c.AST_NODE_CHAR_LITERAL => .char_literal,
+ c.AST_NODE_NUMBER_LITERAL => .number_literal,
+ c.AST_NODE_UNREACHABLE_LITERAL => .unreachable_literal,
+ c.AST_NODE_IDENTIFIER => .identifier,
+ c.AST_NODE_ENUM_LITERAL => .enum_literal,
+ c.AST_NODE_STRING_LITERAL => .string_literal,
+ c.AST_NODE_MULTILINE_STRING_LITERAL => .multiline_string_literal,
+ c.AST_NODE_GROUPED_EXPRESSION => .grouped_expression,
+ c.AST_NODE_BUILTIN_CALL_TWO => .builtin_call_two,
+ c.AST_NODE_BUILTIN_CALL_TWO_COMMA => .builtin_call_two_comma,
+ c.AST_NODE_BUILTIN_CALL => .builtin_call,
+ c.AST_NODE_BUILTIN_CALL_COMMA => .builtin_call_comma,
+ c.AST_NODE_ERROR_SET_DECL => .error_set_decl,
+ c.AST_NODE_CONTAINER_DECL => .container_decl,
+ c.AST_NODE_CONTAINER_DECL_TRAILING => .container_decl_trailing,
+ c.AST_NODE_CONTAINER_DECL_TWO => .container_decl_two,
+ c.AST_NODE_CONTAINER_DECL_TWO_TRAILING => .container_decl_two_trailing,
+ c.AST_NODE_CONTAINER_DECL_ARG => .container_decl_arg,
+ c.AST_NODE_CONTAINER_DECL_ARG_TRAILING => .container_decl_arg_trailing,
+ c.AST_NODE_TAGGED_UNION => .tagged_union,
+ c.AST_NODE_TAGGED_UNION_TRAILING => .tagged_union_trailing,
+ c.AST_NODE_TAGGED_UNION_TWO => .tagged_union_two,
+ c.AST_NODE_TAGGED_UNION_TWO_TRAILING => .tagged_union_two_trailing,
+ c.AST_NODE_TAGGED_UNION_ENUM_TAG => .tagged_union_enum_tag,
+ c.AST_NODE_TAGGED_UNION_ENUM_TAG_TRAILING => .tagged_union_enum_tag_trailing,
+ c.AST_NODE_CONTAINER_FIELD_INIT => .container_field_init,
+ c.AST_NODE_CONTAINER_FIELD_ALIGN => .container_field_align,
+ c.AST_NODE_CONTAINER_FIELD => .container_field,
+ c.AST_NODE_COMPTIME => .@"comptime",
+ c.AST_NODE_NOSUSPEND => .@"nosuspend",
+ c.AST_NODE_BLOCK_TWO => .block_two,
+ c.AST_NODE_BLOCK_TWO_SEMICOLON => .block_two_semicolon,
+ c.AST_NODE_BLOCK => .block,
+ c.AST_NODE_BLOCK_SEMICOLON => .block_semicolon,
+ c.AST_NODE_ASM_SIMPLE => .asm_simple,
+ c.AST_NODE_ASM_LEGACY => .asm_legacy,
+ c.AST_NODE_ASM => .@"asm",
+ c.AST_NODE_ASM_OUTPUT => .asm_output,
+ c.AST_NODE_ASM_INPUT => .asm_input,
+ c.AST_NODE_ERROR_VALUE => .error_value,
+ c.AST_NODE_ERROR_UNION => .error_union,
+ else => undefined,
+ };
}
-test "zig fmt: use of comments and multiline string literals may force the parameters over multiple lines" {
- try testCanonical(
- \\pub fn makeMemUndefined(qzz: []u8) i1 {
- \\ cases.add( // fixed bug foo
- \\ "compile diagnostic string for top level decl type",
- \\ \\export fn entry() void {
- \\ \\ var foo: u32 = @This(){};
- \\ \\}
- \\ , &[_][]const u8{
- \\ "tmp.zig:2:27: error: type 'u32' does not support array initialization",
- \\ });
- \\ @compileError(
- \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
- \\ \\ Consider providing your own hash function.
- \\ \\ unknown-length pointers and C pointers cannot be hashed deeply.
- \\ \\ Consider providing your own hash function.
- \\ );
- \\ return @intCast(doMemCheckClientRequestExpr(0, // default return
- \\ .MakeMemUndefined, @intFromPtr(qzz.ptr), qzz.len, 0, 0, 0));
- \\}
- \\
- \\// This looks like garbage don't do this
- \\const rparen = tree.prevToken(
- \\ // the first token for the annotation expressions is the left
- \\ // parenthesis, hence the need for two prevToken
- \\ if (fn_proto.getAlignExpr()) |align_expr|
- \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))
- \\ else if (fn_proto.getSectionExpr()) |section_expr|
- \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))
- \\ else if (fn_proto.getCallconvExpr()) |callconv_expr|
- \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
- \\ else switch (fn_proto.return_type) {
- \\ .Explicit => |node| node.firstToken(),
- \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),
- \\ .Invalid => unreachable,
- \\ });
- \\
- );
+fn toIndex(v: u32) Ast.Node.Index {
+ return @enumFromInt(v);
}
-test "zig fmt: single argument trailing commas in @builtins()" {
- try testCanonical(
- \\pub fn foo(qzz: []u8) i1 {
- \\ @panic(
- \\ foo,
- \\ );
- \\ panic(
- \\ foo,
- \\ );
- \\ @panic(
- \\ foo,
- \\ bar,
- \\ );
- \\}
- \\
- );
+fn toOptIndex(v: u32) Ast.Node.OptionalIndex {
+ return if (v == 0) .none else @enumFromInt(v);
}
-test "zig fmt: trailing comma should force multiline 1 column" {
- try testTransform(
- \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
- \\
- ,
- \\pub const UUID_NULL: uuid_t = [16]u8{
- \\ 0,
- \\ 0,
- \\ 0,
- \\ 0,
- \\};
- \\
- );
+fn toExtraIndex(v: u32) Ast.ExtraIndex {
+ return @enumFromInt(v);
}
-test "zig fmt: function params should align nicely" {
- try testCanonical(
- \\pub fn foo() void {
- \\ cases.addRuntimeSafety("slicing operator with sentinel",
- \\ \\const std = @import("std");
- \\ ++ check_panic_msg ++
- \\ \\pub fn main() void {
- \\ \\ var buf = [4]u8{'a','b','c',0};
- \\ \\ const slice = buf[0..:0];
- \\ \\}
- \\ );
- \\}
- \\
- );
+fn toOptTokenIndex(v: u32) Ast.OptionalTokenIndex {
+ return @enumFromInt(v);
}
-test "zig fmt: fn proto end with anytype and comma" {
- try testCanonical(
- \\pub fn format(
- \\ out_stream: anytype,
- \\) !void {}
- \\
- );
-}
+fn zigData(tag: Ast.Node.Tag, lhs: u32, rhs: u32) Ast.Node.Data {
+ return switch (tag) {
+ // data unused
+ .identifier,
+ .string_literal,
+ .char_literal,
+ .number_literal,
+ .unreachable_literal,
+ .anyframe_literal,
+ .enum_literal,
+ .error_value,
+ => .{ .opt_node_and_opt_node = .{ toOptIndex(lhs), toOptIndex(rhs) } },
-test "zig fmt: space after top level doc comment" {
- try testCanonical(
- \\//! top level doc comment
- \\
- \\field: i32,
- \\
- );
-}
+ // .node (single node index)
+ .@"defer",
+ .@"comptime",
+ .@"nosuspend",
+ .@"suspend",
+ .@"resume",
+ .bool_not,
+ .negation,
+ .bit_not,
+ .negation_wrap,
+ .address_of,
+ .@"try",
+ .deref,
+ .optional_type,
+ => .{ .node = toIndex(lhs) },
-test "zig fmt: remove trailing whitespace after container doc comment" {
- try testTransform(
- \\//! top level doc comment
- \\
- ,
- \\//! top level doc comment
- \\
- );
-}
+ // .opt_node (single optional node)
+ .@"return",
+ => .{ .opt_node = toOptIndex(lhs) },
-test "zig fmt: remove trailing whitespace after doc comment" {
- try testTransform(
- \\/// doc comment
- \\a = 0,
- \\
- ,
- \\/// doc comment
- \\a = 0,
- \\
- );
-}
+ // .node_and_node
+ .fn_decl,
+ .container_field_align,
+ .error_union,
+ .@"catch",
+ .equal_equal,
+ .bang_equal,
+ .less_than,
+ .greater_than,
+ .less_or_equal,
+ .greater_or_equal,
+ .assign_mul,
+ .assign_div,
+ .assign_mod,
+ .assign_add,
+ .assign_sub,
+ .assign_shl,
+ .assign_shl_sat,
+ .assign_shr,
+ .assign_bit_and,
+ .assign_bit_xor,
+ .assign_bit_or,
+ .assign_mul_wrap,
+ .assign_add_wrap,
+ .assign_sub_wrap,
+ .assign_mul_sat,
+ .assign_add_sat,
+ .assign_sub_sat,
+ .assign,
+ .merge_error_sets,
+ .mul,
+ .div,
+ .mod,
+ .array_mult,
+ .mul_wrap,
+ .mul_sat,
+ .add,
+ .sub,
+ .array_cat,
+ .add_wrap,
+ .sub_wrap,
+ .add_sat,
+ .sub_sat,
+ .shl,
+ .shl_sat,
+ .shr,
+ .bit_and,
+ .bit_xor,
+ .bit_or,
+ .@"orelse",
+ .bool_and,
+ .bool_or,
+ .array_type,
+ .array_access,
+ .switch_range,
+ => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
-test "zig fmt: for loop with ptr payload and index" {
- try testCanonical(
- \\test {
- \\ for (self.entries.items, 0..) |*item, i| {}
- \\ for (self.entries.items, 0..) |*item, i|
- \\ a = b;
- \\ for (self.entries.items, 0..) |*item, i| a = b;
- \\}
- \\
- );
-}
+ // .opt_node_and_opt_node
+ .fn_proto_simple,
+ .simple_var_decl,
+ .block_two,
+ .block_two_semicolon,
+ .builtin_call_two,
+ .builtin_call_two_comma,
+ .container_decl_two,
+ .container_decl_two_trailing,
+ .tagged_union_two,
+ .tagged_union_two_trailing,
+ .struct_init_dot_two,
+ .struct_init_dot_two_comma,
+ .array_init_dot_two,
+ .array_init_dot_two_comma,
+ => .{ .opt_node_and_opt_node = .{ toOptIndex(lhs), toOptIndex(rhs) } },
-test "zig fmt: proper indent line comment after multi-line single expr while loop" {
- try testCanonical(
- \\test {
- \\ while (a) : (b)
- \\ foo();
- \\
- \\ // bar
- \\ baz();
- \\}
- \\
- );
-}
+ // .node_and_opt_node
+ .call_one,
+ .call_one_comma,
+ .struct_init_one,
+ .struct_init_one_comma,
+ .container_field_init,
+ .aligned_var_decl,
+ => .{ .node_and_opt_node = .{ toIndex(lhs), toOptIndex(rhs) } },
+ // .node_and_node (array_init_one uses node_and_node, not
+ // node_and_opt_node)
+ .array_init_one,
+ .array_init_one_comma,
+ => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
-test "zig fmt: extern function with missing param name" {
- try testCanonical(
- \\extern fn a(
- \\ *b,
- \\ c: *d,
- \\) e;
- \\extern fn f(*g, h: *i) j;
- \\
- );
-}
+ // .opt_node_and_node
+ .ptr_type_aligned,
+ .ptr_type_sentinel,
+ .switch_case_one,
+ .switch_case_inline_one,
+ => .{ .opt_node_and_node = .{ toOptIndex(lhs), toIndex(rhs) } },
+ // .node_and_extra
+ .call,
+ .call_comma,
+ .container_field,
+ .array_type_sentinel,
+ .slice,
+ .slice_sentinel,
+ .array_init,
+ .array_init_comma,
+ .struct_init,
+ .struct_init_comma,
+ .@"switch",
+ .switch_comma,
+ .container_decl_arg,
+ .container_decl_arg_trailing,
+ .tagged_union_enum_tag,
+ .tagged_union_enum_tag_trailing,
+ .@"asm",
+ => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
-test "zig fmt: respect extra newline between switch items" {
- try testCanonical(
- \\const a = switch (b) {
- \\ .c => {},
- \\
- \\ .d,
- \\ .e,
- \\ => f,
- \\};
- \\
- );
-}
+ // .extra_and_node
+ .assign_destructure,
+ .switch_case,
+ .switch_case_inline,
+ .ptr_type,
+ .ptr_type_bit_range,
+ => .{ .extra_and_node = .{ toExtraIndex(lhs), toIndex(rhs) } },
-test "zig fmt: assignment with inline for and inline while" {
- try testCanonical(
- \\const tmp = inline for (items) |item| {};
- \\
- );
+ // .extra_and_opt_node
+ .global_var_decl,
+ .local_var_decl,
+ .fn_proto_multi,
+ .fn_proto_one,
+ .fn_proto,
+ => .{ .extra_and_opt_node = .{ toExtraIndex(lhs), toOptIndex(rhs) } },
- try testCanonical(
- \\const tmp2 = inline while (true) {};
- \\
- );
-}
+ // .extra_range (SubRange)
+ .root,
+ .block,
+ .block_semicolon,
+ .builtin_call,
+ .builtin_call_comma,
+ .container_decl,
+ .container_decl_trailing,
+ .tagged_union,
+ .tagged_union_trailing,
+ .array_init_dot,
+ .array_init_dot_comma,
+ .struct_init_dot,
+ .struct_init_dot_comma,
+ => .{ .extra_range = .{ .start = toExtraIndex(lhs), .end = toExtraIndex(rhs) } },
-test "zig fmt: saturating arithmetic" {
- try testCanonical(
- \\test {
- \\ const actual = switch (op) {
- \\ .add => a +| b,
- \\ .sub => a -| b,
- \\ .mul => a *| b,
- \\ .shl => a <<| b,
- \\ };
- \\ switch (op) {
- \\ .add => actual +|= b,
- \\ .sub => actual -|= b,
- \\ .mul => actual *|= b,
- \\ .shl => actual <<|= b,
- \\ }
- \\}
- \\
- );
-}
+ // .node_and_token
+ .grouped_expression,
+ .asm_input,
+ .asm_simple,
+ .field_access,
+ .unwrap_optional,
+ => .{ .node_and_token = .{ toIndex(lhs), rhs } },
-test "zig fmt: insert trailing comma if there are comments between switch values" {
- try testTransform(
- \\const a = switch (b) {
- \\ .c => {},
- \\
- \\ .d, // foobar
- \\ .e
- \\ => f,
- \\
- \\ .g, .h
- \\ // comment
- \\ => i,
- \\};
- \\
- ,
- \\const a = switch (b) {
- \\ .c => {},
- \\
- \\ .d, // foobar
- \\ .e,
- \\ => f,
- \\
- \\ .g,
- \\ .h,
- \\ // comment
- \\ => i,
- \\};
- \\
- );
-}
+ // .opt_node_and_token
+ .asm_output,
+ => .{ .opt_node_and_token = .{ toOptIndex(lhs), rhs } },
-test "zig fmt: insert trailing comma if comments in array init" {
- try testTransform(
- \\var a = .{
- \\ "foo", //
- \\ "bar"
- \\};
- \\var a = .{
- \\ "foo",
- \\ "bar" //
- \\};
- \\var a = .{
- \\ "foo",
- \\ "//"
- \\};
- \\var a = .{
- \\ "foo",
- \\ "//" //
- \\};
- \\
- ,
- \\var a = .{
- \\ "foo", //
- \\ "bar",
- \\};
- \\var a = .{
- \\ "foo",
- \\ "bar", //
- \\};
- \\var a = .{ "foo", "//" };
- \\var a = .{
- \\ "foo",
- \\ "//", //
- \\};
- \\
- );
-}
+ // .opt_token_and_node
+ .test_decl,
+ .@"errdefer",
+ => .{ .opt_token_and_node = .{ toOptTokenIndex(lhs), toIndex(rhs) } },
-test "zig fmt: make single-line if no trailing comma" {
- try testTransform(
- \\test "function call no trailing comma" {
- \\ foo(
- \\ 1,
- \\ 2
- \\ );
- \\}
- \\
- ,
- \\test "function call no trailing comma" {
- \\ foo(1, 2);
- \\}
- \\
- );
+ // .opt_token_and_opt_node
+ .@"break",
+ .@"continue",
+ => .{ .opt_token_and_opt_node = .{ toOptTokenIndex(lhs), toOptIndex(rhs) } },
- try testTransform(
- \\test "struct no trailing comma" {
- \\ const a = .{
- \\ .foo = 1,
- \\ .bar = 2
- \\ };
- \\}
- \\
- ,
- \\test "struct no trailing comma" {
- \\ const a = .{ .foo = 1, .bar = 2 };
- \\}
- \\
- );
+ // .token_and_token
+ .error_set_decl,
+ .multiline_string_literal,
+ => .{ .token_and_token = .{ lhs, rhs } },
- try testTransform(
- \\test "array no trailing comma" {
- \\ var stream = multiOutStream(.{
- \\ fbs1.outStream(),
- \\ fbs2.outStream()
- \\ });
- \\}
- \\
- ,
- \\test "array no trailing comma" {
- \\ var stream = multiOutStream(.{ fbs1.outStream(), fbs2.outStream() });
- \\}
- \\
- );
-}
+ // .token_and_node
+ .anyframe_type,
+ => .{ .token_and_node = .{ lhs, toIndex(rhs) } },
-test "zig fmt: preserve container doc comment in container without trailing comma" {
- try testTransform(
- \\const A = enum(u32) {
- \\//! comment
- \\_ };
- \\
- ,
- \\const A = enum(u32) {
- \\ //! comment
- \\ _,
- \\};
- \\
- );
-}
+ // .node_and_node for slice_open (lhs[rhs..])
+ .slice_open,
+ => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
+ .while_simple,
+ .for_simple,
+ .if_simple,
+ => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
-test "zig fmt: no space before newline before multiline string" {
- try testCanonical(
- \\const S = struct {
- \\ text: []const u8,
- \\ comment: []const u8,
- \\};
- \\
- \\test {
- \\ const s1 = .{
- \\ .text =
- \\ \\hello
- \\ \\world
- \\ ,
- \\ .comment = "test",
- \\ };
- \\ _ = s1;
- \\ const s2 = .{
- \\ .comment = "test",
- \\ .text =
- \\ \\hello
- \\ \\world
- \\ ,
- \\ };
- \\ _ = s2;
- \\}
- \\
- );
-}
+ .while_cont,
+ .@"while",
+ .@"if",
+ => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
-test "zig fmt: don't canonicalize _ in enums" {
- try testTransform(
- \\const A = enum {
- \\ first,
- \\ second,
- \\ third,
- \\ _,
- \\};
- \\const B = enum {
- \\ @"_",
- \\ @"__",
- \\ @"___",
- \\ @"____",
- \\};
- \\const C = struct {
- \\ @"_": u8,
- \\ @"__": u8,
- \\ @"___": u8,
- \\ @"____": u8,
- \\};
- \\const D = union {
- \\ @"_": u8,
- \\ @"__": u8,
- \\ @"___": u8,
- \\ @"____": u8,
- \\};
- \\
- ,
- \\const A = enum {
- \\ first,
- \\ second,
- \\ third,
- \\ _,
- \\};
- \\const B = enum {
- \\ @"_",
- \\ __,
- \\ ___,
- \\ ____,
- \\};
- \\const C = struct {
- \\ _: u8,
- \\ __: u8,
- \\ ___: u8,
- \\ ____: u8,
- \\};
- \\const D = union {
- \\ _: u8,
- \\ __: u8,
- \\ ___: u8,
- \\ ____: u8,
- \\};
- \\
- );
-}
+ .for_range,
+ => .{ .node_and_opt_node = .{ toIndex(lhs), toOptIndex(rhs) } },
-test "zig fmt: pointer type syntax to index" {
- try testCanonical(
- \\test {
- \\ _ = .{}[*0];
- \\}
- \\
- );
-}
+ .@"for",
+ => .{ .@"for" = .{ toExtraIndex(lhs), @bitCast(rhs) } },
-test "zig fmt: binop indentation in if statement" {
- try testCanonical(
- \\test {
- \\ if (first_param_type.isGenericPoison() or
- \\ (first_param_type.zigTypeTag(zcu) == .pointer and
- \\ (first_param_type.ptrSize(zcu) == .One or
- \\ first_param_type.ptrSize(zcu) == .C) and
- \\ first_param_type.childType(zcu).eql(concrete_ty, zcu)))
- \\ {
- \\ f(x);
- \\ }
- \\}
- \\
- );
+ .asm_legacy,
+ => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
+ };
}
+// zigAst converts a c.Ast to std.Zig.Ast. The resulting Ast should be freed with deinit().
+fn zigAst(gpa: Allocator, c_ast: c.Ast) !Ast {
+ var tokens = Ast.TokenList{};
+ try tokens.resize(gpa, c_ast.tokens.len);
+ errdefer tokens.deinit(gpa);
-test "zig fmt: test indentation of if expressions" {
- try testCanonical(
- \\test {
- \\ const foo = 1 +
- \\ if (1 == 2)
- \\ 2
- \\ else
- \\ 0;
- \\
- \\ const foo = 1 + if (1 == 2)
- \\ 2
- \\ else
- \\ 0;
- \\
- \\ errval catch |e|
- \\ if (e == error.Meow)
- \\ return 0x1F408
- \\ else
- \\ unreachable;
- \\
- \\ errval catch |e| if (e == error.Meow)
- \\ return 0x1F408
- \\ else
- \\ unreachable;
- \\
- \\ return if (1 == 2)
- \\ 1
- \\ else if (3 > 4)
- \\ 2
- \\ else
- \\ 0;
- \\}
- \\
- );
-}
+ for (0..c_ast.tokens.len) |i|
+ tokens.set(i, .{
+ .tag = zigToken(c_ast.tokens.tags[i]),
+ .start = c_ast.tokens.starts[i],
+ });
+ var nodes = Ast.NodeList{};
+ try nodes.resize(gpa, c_ast.nodes.len);
+ errdefer nodes.deinit(gpa);
-test "Ast header smoke test" {
- try std.testing.expectEqual(zigNode(c.AST_NODE_IF), Ast.Node.Tag.@"if");
-}
+ for (0..c_ast.nodes.len) |i| {
+ const tag = zigNode(c_ast.nodes.tags[i]);
+ nodes.set(i, .{
+ .tag = tag,
+ .main_token = c_ast.nodes.main_tokens[i],
+ .data = zigData(tag, c_ast.nodes.datas[i].lhs, c_ast.nodes.datas[i].rhs),
+ });
+ }
-test "my function" {
- try testCanonical(
- \\pub fn main() void {
- \\ @panic("hello");
- \\}
- \\
- );
+ const extra_data = try gpa.alloc(u32, c_ast.extra_data.len);
+ errdefer gpa.free(extra_data);
+ @memcpy(extra_data, c_ast.extra_data.arr[0..c_ast.extra_data.len]);
+
+ // creating a dummy `errors` slice, so deinit can free it.
+ const errors = try gpa.alloc(Ast.Error, 0);
+ errdefer gpa.free(errors);
+
+ return Ast{
+ .source = c_ast.source[0..c_ast.source_len :0],
+ .mode = .zig,
+ .tokens = tokens.slice(),
+ .nodes = nodes.slice(),
+ .extra_data = extra_data,
+ .errors = errors,
+ };
}
+// copy-past from parser_test.zig