Reorder all test blocks in parser_test.zig to match the order
they appear in the upstream zig/lib/std/zig/parser_test.zig.
Tests not in upstream ("Ast header smoke test", "my function")
are placed at the end.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2350 lines
56 KiB
Zig
2350 lines
56 KiB
Zig
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 => .@"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,
|
|
.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_simple,
|
|
.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);
|
|
}
|
|
|
|
test "zig fmt: remove extra whitespace at start and end of file with comment between" {
|
|
try testTransform(
|
|
\\
|
|
\\
|
|
\\// hello
|
|
\\
|
|
\\
|
|
,
|
|
\\// hello
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: tuple struct" {
|
|
try testCanonical(
|
|
\\const T = struct {
|
|
\\ /// doc comment on tuple field
|
|
\\ comptime comptime u32,
|
|
\\ /// another doc comment on tuple field
|
|
\\ *u32 = 1,
|
|
\\ // needs to be wrapped in parentheses to not be parsed as a function decl
|
|
\\ (fn () void) align(1),
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: respect line breaks in struct field value declaration" {
|
|
try testCanonical(
|
|
\\const Foo = struct {
|
|
\\ bar: u32 =
|
|
\\ 42,
|
|
\\ bar: u32 =
|
|
\\ // a comment
|
|
\\ 42,
|
|
\\ bar: u32 =
|
|
\\ 42,
|
|
\\ // a comment
|
|
\\ bar: []const u8 =
|
|
\\ \\ foo
|
|
\\ \\ bar
|
|
\\ \\ baz
|
|
\\ ,
|
|
\\ bar: u32 =
|
|
\\ blk: {
|
|
\\ break :blk 42;
|
|
\\ },
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: respect line breaks before functions" {
|
|
try testCanonical(
|
|
\\const std = @import("std");
|
|
\\
|
|
\\inline fn foo() void {}
|
|
\\
|
|
\\noinline fn foo() void {}
|
|
\\
|
|
\\export fn foo() void {}
|
|
\\
|
|
\\extern fn foo() void;
|
|
\\
|
|
\\extern "foo" fn foo() void;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: simple top level comptime block" {
|
|
try testCanonical(
|
|
\\// line comment
|
|
\\comptime {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: two spaced line comments before decl" {
|
|
try testCanonical(
|
|
\\// line comment
|
|
\\
|
|
\\// another
|
|
\\comptime {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: respect line breaks after var declarations" {
|
|
try testCanonical(
|
|
\\const crc =
|
|
\\ lookup_tables[0][p[7]] ^
|
|
\\ lookup_tables[1][p[6]] ^
|
|
\\ lookup_tables[2][p[5]] ^
|
|
\\ lookup_tables[3][p[4]] ^
|
|
\\ lookup_tables[4][@as(u8, self.crc >> 24)] ^
|
|
\\ lookup_tables[5][@as(u8, self.crc >> 16)] ^
|
|
\\ lookup_tables[6][@as(u8, self.crc >> 8)] ^
|
|
\\ lookup_tables[7][@as(u8, self.crc >> 0)];
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: multiline string mixed with comments" {
|
|
try testCanonical(
|
|
\\const s1 =
|
|
\\ //\\one
|
|
\\ \\two)
|
|
\\ \\three
|
|
\\;
|
|
\\const s2 =
|
|
\\ \\one
|
|
\\ \\two)
|
|
\\ //\\three
|
|
\\;
|
|
\\const s3 =
|
|
\\ \\one
|
|
\\ //\\two)
|
|
\\ \\three
|
|
\\;
|
|
\\const s4 =
|
|
\\ \\one
|
|
\\ //\\two
|
|
\\ \\three
|
|
\\ //\\four
|
|
\\ \\five
|
|
\\;
|
|
\\const a =
|
|
\\ 1;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: empty file" {
|
|
try testCanonical(
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: file ends in comment" {
|
|
try testTransform(
|
|
\\ //foobar
|
|
,
|
|
\\//foobar
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: file ends in multi line comment" {
|
|
try testTransform(
|
|
\\ \\foobar
|
|
,
|
|
\\\\foobar
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: file ends in comment after var decl" {
|
|
try testTransform(
|
|
\\const x = 42;
|
|
\\ //foobar
|
|
,
|
|
\\const x = 42;
|
|
\\//foobar
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: if statement" {
|
|
try testCanonical(
|
|
\\test "" {
|
|
\\ if (optional()) |some|
|
|
\\ bar = some.foo();
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: top-level fields" {
|
|
try testCanonical(
|
|
\\a: did_you_know,
|
|
\\b: all_files_are,
|
|
\\structs: ?x,
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: top-level tuple function call type" {
|
|
try testCanonical(
|
|
\\foo()
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: top-level bare asterisk+identifier" {
|
|
try testCanonical(
|
|
\\*x
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: top-level bare asterisk+asterisk+identifier" {
|
|
try testCanonical(
|
|
\\**x
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: errdefer with payload" {
|
|
try testCanonical(
|
|
\\pub fn main() anyerror!void {
|
|
\\ errdefer |a| x += 1;
|
|
\\ errdefer |a| {}
|
|
\\ errdefer |a| {
|
|
\\ x += 1;
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: nosuspend block" {
|
|
try testCanonical(
|
|
\\pub fn main() anyerror!void {
|
|
\\ nosuspend {
|
|
\\ var foo: Foo = .{ .bar = 42 };
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, single line" {
|
|
try testCanonical(
|
|
\\const X = struct { foo: i32 };
|
|
\\const X = struct { foo: i32, bar: i32 };
|
|
\\const X = struct { foo: i32 = 1, bar: i32 = 2 };
|
|
\\const X = struct { foo: i32 align(4), bar: i32 align(4) };
|
|
\\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, one item, multi line trailing comma" {
|
|
try testCanonical(
|
|
\\test "" {
|
|
\\ comptime {
|
|
\\ const X = struct {
|
|
\\ x: i32,
|
|
\\ };
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, no trailing comma on separate line" {
|
|
try testTransform(
|
|
\\test "" {
|
|
\\ comptime {
|
|
\\ const X = struct {
|
|
\\ x: i32
|
|
\\ };
|
|
\\ }
|
|
\\}
|
|
\\
|
|
,
|
|
\\test "" {
|
|
\\ comptime {
|
|
\\ const X = struct { x: i32 };
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, line break, no trailing comma" {
|
|
try testTransform(
|
|
\\const X = struct {
|
|
\\ foo: i32, bar: i8 };
|
|
,
|
|
\\const X = struct { foo: i32, bar: i8 };
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, transform trailing comma" {
|
|
try testTransform(
|
|
\\const X = struct {
|
|
\\ foo: i32, bar: i8, };
|
|
,
|
|
\\const X = struct {
|
|
\\ foo: i32,
|
|
\\ bar: i8,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, comment, add trailing comma" {
|
|
try testTransform(
|
|
\\const X = struct {
|
|
\\ foo: i32, // foo
|
|
\\ bar: i8
|
|
\\};
|
|
,
|
|
\\const X = struct {
|
|
\\ foo: i32, // foo
|
|
\\ bar: i8,
|
|
\\};
|
|
\\
|
|
);
|
|
try testTransform(
|
|
\\const X = struct {
|
|
\\ foo: i32 // foo
|
|
\\};
|
|
,
|
|
\\const X = struct {
|
|
\\ foo: i32, // foo
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, multiline string, add trailing comma" {
|
|
try testTransform(
|
|
\\const X = struct {
|
|
\\ foo: []const u8 =
|
|
\\ \\ foo
|
|
\\ ,
|
|
\\ bar: i8
|
|
\\};
|
|
,
|
|
\\const X = struct {
|
|
\\ foo: []const u8 =
|
|
\\ \\ foo
|
|
\\ ,
|
|
\\ bar: i8,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container declaration, doc comment on member, add trailing comma" {
|
|
try testTransform(
|
|
\\pub const Pos = struct {
|
|
\\ /// X-axis.
|
|
\\ x: u32,
|
|
\\ /// Y-axis.
|
|
\\ y: u32
|
|
\\};
|
|
,
|
|
\\pub const Pos = struct {
|
|
\\ /// X-axis.
|
|
\\ x: u32,
|
|
\\ /// Y-axis.
|
|
\\ y: u32,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: remove empty lines at start/end of container decl" {
|
|
try testTransform(
|
|
\\const X = struct {
|
|
\\
|
|
\\ foo: i32,
|
|
\\
|
|
\\ bar: i8,
|
|
\\
|
|
\\};
|
|
\\
|
|
,
|
|
\\const X = struct {
|
|
\\ foo: i32,
|
|
\\
|
|
\\ bar: i8,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: remove empty lines at start/end of block" {
|
|
try testTransform(
|
|
\\test {
|
|
\\
|
|
\\ if (foo) {
|
|
\\ foo();
|
|
\\ }
|
|
\\
|
|
\\}
|
|
\\
|
|
,
|
|
\\test {
|
|
\\ if (foo) {
|
|
\\ foo();
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: allow empty line before comment at start of block" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\
|
|
\\ // foo
|
|
\\ const x = 42;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: trailing comma in fn parameter list" {
|
|
try testCanonical(
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) align(8) i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) addrspace(.generic) i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) linksection(".text") i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) callconv(.c) i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) align(8) linksection(".text") i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) align(8) callconv(.c) i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) align(8) linksection(".text") callconv(.c) i32 {}
|
|
\\pub fn f(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) linksection(".text") callconv(.c) i32 {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comptime struct field" {
|
|
try testCanonical(
|
|
\\const Foo = struct {
|
|
\\ a: i32,
|
|
\\ comptime b: i32 = 1234,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: break from block" {
|
|
try testCanonical(
|
|
\\const a = blk: {
|
|
\\ break :blk 42;
|
|
\\};
|
|
\\const b = blk: {
|
|
\\ break :blk;
|
|
\\};
|
|
\\const c = {
|
|
\\ break 42;
|
|
\\};
|
|
\\const d = {
|
|
\\ break;
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: grouped expressions (parentheses)" {
|
|
try testCanonical(
|
|
\\const r = (x + y) * (a + b);
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: c pointer type" {
|
|
try testCanonical(
|
|
\\pub extern fn repro() [*c]const u8;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: builtin call with trailing comma" {
|
|
try testCanonical(
|
|
\\pub fn main() void {
|
|
\\ @breakpoint();
|
|
\\ _ = @intFromBool(a);
|
|
\\ _ = @call(
|
|
\\ a,
|
|
\\ b,
|
|
\\ c,
|
|
\\ );
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array types last token" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [40]u32;
|
|
\\}
|
|
\\
|
|
\\test {
|
|
\\ const x = [40:0]u32;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: sentinel-terminated array type" {
|
|
try testCanonical(
|
|
\\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
|
|
\\ return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: sentinel-terminated slice type" {
|
|
try testCanonical(
|
|
\\pub fn toSlice(self: Buffer) [:0]u8 {
|
|
\\ return self.list.toSlice()[0..self.len()];
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: pointer-to-one with modifiers" {
|
|
try testCanonical(
|
|
\\const x: *u32 = undefined;
|
|
\\const y: *allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
|
|
\\const z: *allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: pointer-to-many with modifiers" {
|
|
try testCanonical(
|
|
\\const x: [*]u32 = undefined;
|
|
\\const y: [*]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
|
|
\\const z: [*]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: sentinel pointer with modifiers" {
|
|
try testCanonical(
|
|
\\const x: [*:42]u32 = undefined;
|
|
\\const y: [*:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
|
|
\\const y: [*:42]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: c pointer with modifiers" {
|
|
try testCanonical(
|
|
\\const x: [*c]u32 = undefined;
|
|
\\const y: [*c]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
|
|
\\const z: [*c]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: slice with modifiers" {
|
|
try testCanonical(
|
|
\\const x: []u32 = undefined;
|
|
\\const y: []allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: sentinel slice with modifiers" {
|
|
try testCanonical(
|
|
\\const x: [:42]u32 = undefined;
|
|
\\const y: [:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon literal in array" {
|
|
try testCanonical(
|
|
\\var arr: [2]Foo = .{
|
|
\\ .{ .a = 2 },
|
|
\\ .{ .b = 3 },
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: alignment in anonymous literal" {
|
|
try testTransform(
|
|
\\const a = .{
|
|
\\ "U", "L", "F",
|
|
\\ "U'",
|
|
\\ "L'",
|
|
\\ "F'",
|
|
\\};
|
|
\\
|
|
,
|
|
\\const a = .{
|
|
\\ "U", "L", "F",
|
|
\\ "U'", "L'", "F'",
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon struct literal 0 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{};
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon struct literal 1 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{ .a = b };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon struct literal 1 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{
|
|
\\ .a = b,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon struct literal 2 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{ .a = b, .c = d };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon struct literal 2 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{
|
|
\\ .a = b,
|
|
\\ .c = d,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon struct literal 3 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{ .a = b, .c = d, .e = f };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon struct literal 3 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{
|
|
\\ .a = b,
|
|
\\ .c = d,
|
|
\\ .e = f,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: struct literal 0 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = X{};
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: struct literal 1 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = X{ .a = b };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: Unicode code point literal larger than u8" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = X{
|
|
\\ .a = b,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: struct literal 2 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = X{ .a = b, .c = d };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: struct literal 2 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = X{
|
|
\\ .a = b,
|
|
\\ .c = d,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: struct literal 3 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = X{ .a = b, .c = d, .e = f };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: struct literal 3 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = X{
|
|
\\ .a = b,
|
|
\\ .c = d,
|
|
\\ .e = f,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon list literal 1 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{a};
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon list literal 1 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{
|
|
\\ a,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon list literal 2 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{ a, b };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon list literal 2 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{
|
|
\\ a,
|
|
\\ b,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon list literal 3 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{ a, b, c };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: anon list literal 3 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = .{
|
|
\\ a,
|
|
\\ // foo
|
|
\\ b,
|
|
\\
|
|
\\ c,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array literal 0 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [_]u32{};
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array literal 1 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [_]u32{a};
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array literal 1 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [1]u32{
|
|
\\ a,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array literal 2 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [_]u32{ a, b };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array literal 2 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [2]u32{
|
|
\\ a,
|
|
\\ b,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array literal 3 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [_]u32{ a, b, c };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: array literal 3 element comma" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [3]u32{
|
|
\\ a,
|
|
\\ b,
|
|
\\ c,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: sentinel array literal 1 element" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const x = [_:9000]u32{a};
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: slices" {
|
|
try testCanonical(
|
|
\\const a = b[0..];
|
|
\\const c = d[0..1];
|
|
\\const d = f[0.. :0];
|
|
\\const e = f[0..1 :0];
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: slices with spaces in bounds" {
|
|
try testCanonical(
|
|
\\const a = b[0 + 0 ..];
|
|
\\const c = d[0 + 0 .. 1];
|
|
\\const c = d[0 + 0 .. :0];
|
|
\\const e = f[0 .. 1 + 1 :0];
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: block in slice expression" {
|
|
try testCanonical(
|
|
\\const a = b[{
|
|
\\ _ = x;
|
|
\\}..];
|
|
\\const c = d[0..{
|
|
\\ _ = x;
|
|
\\ _ = y;
|
|
\\}];
|
|
\\const e = f[0..1 :{
|
|
\\ _ = x;
|
|
\\ _ = y;
|
|
\\ _ = z;
|
|
\\}];
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: tagged union with enum values" {
|
|
try testCanonical(
|
|
\\const MultipleChoice2 = union(enum(u32)) {
|
|
\\ Unspecified1: i32,
|
|
\\ A: f32 = 20,
|
|
\\ Unspecified2: void,
|
|
\\ B: bool = 40,
|
|
\\ Unspecified3: i32,
|
|
\\ C: i8 = 60,
|
|
\\ Unspecified4: void,
|
|
\\ D: void = 1000,
|
|
\\ Unspecified5: i32,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: tagged union enum tag last token" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ const U = union(enum(u32)) {};
|
|
\\}
|
|
\\
|
|
\\test {
|
|
\\ const U = union(enum(u32)) { foo };
|
|
\\}
|
|
\\
|
|
\\test {
|
|
\\ const U = union(enum(u32)) {
|
|
\\ foo,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: allowzero pointer" {
|
|
try testCanonical(
|
|
\\const T = [*]allowzero const u8;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: empty enum decls" {
|
|
try testCanonical(
|
|
\\const A = enum {};
|
|
\\const B = enum(u32) {};
|
|
\\const C = extern enum(c_int) {};
|
|
\\const D = packed enum(u8) {};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: empty union decls" {
|
|
try testCanonical(
|
|
\\const A = union {};
|
|
\\const B = union(enum) {};
|
|
\\const C = union(Foo) {};
|
|
\\const D = extern union {};
|
|
\\const E = packed union {};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: enum literal" {
|
|
try testCanonical(
|
|
\\const x = .hi;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: enum literal inside array literal" {
|
|
try testCanonical(
|
|
\\test "enums in arrays" {
|
|
\\ var colors = []Color{.Green};
|
|
\\ colors = []Colors{ .Green, .Cyan };
|
|
\\ colors = []Colors{
|
|
\\ .Grey,
|
|
\\ .Green,
|
|
\\ .Cyan,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: character literal larger than u8" {
|
|
try testCanonical(
|
|
\\const x = '\u{01f4a9}';
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: infix operator and then multiline string literal" {
|
|
try testCanonical(
|
|
\\const x = "" ++
|
|
\\ \\ hi
|
|
\\;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: infix operator and then multiline string literal over multiple lines" {
|
|
try testCanonical(
|
|
\\const x = "" ++
|
|
\\ \\ hi0
|
|
\\ \\ hi1
|
|
\\ \\ hi2
|
|
\\;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: C pointers" {
|
|
try testCanonical(
|
|
\\const Ptr = [*c]i32;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: threadlocal" {
|
|
try testCanonical(
|
|
\\threadlocal var x: i32 = 1234;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: linksection" {
|
|
try testCanonical(
|
|
\\export var aoeu: u64 linksection(".text.derp") = 1234;
|
|
\\export fn _start() linksection(".text.boot") callconv(.naked) noreturn {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: addrspace" {
|
|
try testCanonical(
|
|
\\export var python_length: u64 align(1) addrspace(.generic);
|
|
\\export var python_color: Color addrspace(.generic) = .green;
|
|
\\export var python_legs: u0 align(8) addrspace(.generic) linksection(".python") = 0;
|
|
\\export fn python_hiss() align(8) addrspace(.generic) linksection(".python") void;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: correctly space struct fields with doc comments" {
|
|
try testTransform(
|
|
\\pub const S = struct {
|
|
\\ /// A
|
|
\\ a: u8,
|
|
\\ /// B
|
|
\\ /// B (cont)
|
|
\\ b: u8,
|
|
\\
|
|
\\
|
|
\\ /// C
|
|
\\ c: u8,
|
|
\\};
|
|
\\
|
|
,
|
|
\\pub const S = struct {
|
|
\\ /// A
|
|
\\ a: u8,
|
|
\\ /// B
|
|
\\ /// B (cont)
|
|
\\ b: u8,
|
|
\\
|
|
\\ /// C
|
|
\\ c: u8,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: doc comments on param decl" {
|
|
try testCanonical(
|
|
\\pub const Allocator = struct {
|
|
\\ shrinkFn: fn (
|
|
\\ self: Allocator,
|
|
\\ /// Guaranteed to be the same as what was returned from most recent call to
|
|
\\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
|
|
\\ old_mem: []u8,
|
|
\\ /// Guaranteed to be the same as what was returned from most recent call to
|
|
\\ /// `allocFn`, `reallocFn`, or `shrinkFn`.
|
|
\\ old_alignment: u29,
|
|
\\ /// Guaranteed to be less than or equal to `old_mem.len`.
|
|
\\ new_byte_count: usize,
|
|
\\ /// Guaranteed to be less than or equal to `old_alignment`.
|
|
\\ new_alignment: u29,
|
|
\\ ) []u8,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: aligned struct field" {
|
|
try testCanonical(
|
|
\\pub const S = struct {
|
|
\\ f: i32 align(32),
|
|
\\};
|
|
\\
|
|
);
|
|
try testCanonical(
|
|
\\pub const S = struct {
|
|
\\ f: i32 align(32) = 1,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comment to disable/enable zig fmt first" {
|
|
try testCanonical(
|
|
\\// Test trailing comma syntax
|
|
\\// zig fmt: off
|
|
\\
|
|
\\const struct_trailing_comma = struct { x: i32, y: i32, };
|
|
);
|
|
}
|
|
|
|
test "zig fmt: 'zig fmt: (off|on)' can be surrounded by arbitrary whitespace" {
|
|
try testTransform(
|
|
\\// Test trailing comma syntax
|
|
\\// zig fmt: off
|
|
\\
|
|
\\const struct_trailing_comma = struct { x: i32, y: i32, };
|
|
\\
|
|
\\// zig fmt: on
|
|
,
|
|
\\// Test trailing comma syntax
|
|
\\// zig fmt: off
|
|
\\
|
|
\\const struct_trailing_comma = struct { x: i32, y: i32, };
|
|
\\
|
|
\\// zig fmt: on
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comment to disable/enable zig fmt" {
|
|
try testTransform(
|
|
\\const a = b;
|
|
\\// zig fmt: off
|
|
\\const c = d;
|
|
\\// zig fmt: on
|
|
\\const e = f;
|
|
,
|
|
\\const a = b;
|
|
\\// zig fmt: off
|
|
\\const c = d;
|
|
\\// zig fmt: on
|
|
\\const e = f;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: line comment following 'zig fmt: off'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\// Test
|
|
\\const e = f;
|
|
);
|
|
}
|
|
|
|
test "zig fmt: doc comment following 'zig fmt: off'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\/// test
|
|
\\const e = f;
|
|
);
|
|
}
|
|
|
|
test "zig fmt: line and doc comment following 'zig fmt: off'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\// test 1
|
|
\\/// test 2
|
|
\\const e = f;
|
|
);
|
|
}
|
|
|
|
test "zig fmt: doc and line comment following 'zig fmt: off'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\/// test 1
|
|
\\// test 2
|
|
\\const e = f;
|
|
);
|
|
}
|
|
|
|
test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\// zig fmt: on
|
|
\\// zig fmt: off
|
|
\\const e = f;
|
|
\\// zig fmt: off
|
|
\\// zig fmt: on
|
|
\\// zig fmt: off
|
|
\\const a = b;
|
|
\\// zig fmt: on
|
|
\\const c = d;
|
|
\\// zig fmt: on
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: line comment following 'zig fmt: on'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\const e = f;
|
|
\\// zig fmt: on
|
|
\\// test
|
|
\\const e = f;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: doc comment following 'zig fmt: on'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\const e = f;
|
|
\\// zig fmt: on
|
|
\\/// test
|
|
\\const e = f;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: line and doc comment following 'zig fmt: on'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\const e = f;
|
|
\\// zig fmt: on
|
|
\\// test1
|
|
\\/// test2
|
|
\\const e = f;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: doc and line comment following 'zig fmt: on'" {
|
|
try testCanonical(
|
|
\\// zig fmt: off
|
|
\\const e = f;
|
|
\\// zig fmt: on
|
|
\\/// test1
|
|
\\// test2
|
|
\\const e = f;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: pointer of unknown length" {
|
|
try testCanonical(
|
|
\\fn foo(ptr: [*]u8) void {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: spaces around slice operator" {
|
|
try testCanonical(
|
|
\\var a = b[c..d];
|
|
\\var a = b[c..d :0];
|
|
\\var a = b[c + 1 .. d];
|
|
\\var a = b[c + 1 ..];
|
|
\\var a = b[c .. d + 1];
|
|
\\var a = b[c .. d + 1 :0];
|
|
\\var a = b[c.a..d.e];
|
|
\\var a = b[c.a..d.e :0];
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: 2nd arg multiline string" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ cases.addAsm("hello world linux x86_64",
|
|
\\ \\.text
|
|
\\ , "Hello, world!\n");
|
|
\\}
|
|
\\
|
|
);
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ cases.addAsm("hello world linux x86_64",
|
|
\\ \\.text
|
|
\\ , "Hello, world!\n", "Hello, world!\n");
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: final arg multiline string" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ cases.addAsm("hello world linux x86_64", "Hello, world!\n",
|
|
\\ \\.text
|
|
\\ );
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: function call with multiline argument" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ self.user_input_options.put(name, UserInputOption{
|
|
\\ .name = name,
|
|
\\ .used = false,
|
|
\\ });
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: if-else with comment before else" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ // cexp(finite|nan +- i inf|nan) = nan + i nan
|
|
\\ if ((hx & 0x7fffffff) != 0x7f800000) {
|
|
\\ return Complex(f32).init(y - y, y - y);
|
|
\\ } // cexp(-inf +- i inf|nan) = 0 + i0
|
|
\\ else if (hx & 0x80000000 != 0) {
|
|
\\ return Complex(f32).init(0, 0);
|
|
\\ } // cexp(+inf +- i inf|nan) = inf + i nan
|
|
\\ else {
|
|
\\ return Complex(f32).init(x, y - y);
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: if nested" {
|
|
try testCanonical(
|
|
\\pub fn foo() void {
|
|
\\ return if ((aInt & bInt) >= 0)
|
|
\\ if (aInt < bInt)
|
|
\\ GE_LESS
|
|
\\ else if (aInt == bInt)
|
|
\\ GE_EQUAL
|
|
\\ else
|
|
\\ GE_GREATER
|
|
\\ // comment
|
|
\\ else if (aInt > bInt)
|
|
\\ GE_LESS
|
|
\\ else if (aInt == bInt)
|
|
\\ GE_EQUAL
|
|
\\ else
|
|
\\ GE_GREATER;
|
|
\\ // comment
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: respect line breaks in if-else" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ return if (cond) a else b;
|
|
\\ return if (cond)
|
|
\\ a
|
|
\\ else
|
|
\\ b;
|
|
\\ return if (cond)
|
|
\\ a
|
|
\\ else if (cond)
|
|
\\ b
|
|
\\ else
|
|
\\ c;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: respect line breaks after infix operators" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ self.crc =
|
|
\\ lookup_tables[0][p[7]] ^
|
|
\\ lookup_tables[1][p[6]] ^
|
|
\\ lookup_tables[2][p[5]] ^
|
|
\\ lookup_tables[3][p[4]] ^
|
|
\\ lookup_tables[4][@as(u8, self.crc >> 24)] ^
|
|
\\ lookup_tables[5][@as(u8, self.crc >> 16)] ^
|
|
\\ lookup_tables[6][@as(u8, self.crc >> 8)] ^
|
|
\\ lookup_tables[7][@as(u8, self.crc >> 0)];
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: fn decl with trailing comma" {
|
|
try testTransform(
|
|
\\fn foo(a: i32, b: i32,) void {}
|
|
,
|
|
\\fn foo(
|
|
\\ a: i32,
|
|
\\ b: i32,
|
|
\\) void {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: enum decl with no trailing comma" {
|
|
try testTransform(
|
|
\\const StrLitKind = enum {Normal, C};
|
|
,
|
|
\\const StrLitKind = enum { Normal, C };
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: struct literal no trailing comma" {
|
|
try testTransform(
|
|
\\const a = foo{ .x = 1, .y = 2 };
|
|
\\const a = foo{ .x = 1,
|
|
\\ .y = 2 };
|
|
\\const a = foo{ .x = 1,
|
|
\\ .y = 2, };
|
|
,
|
|
\\const a = foo{ .x = 1, .y = 2 };
|
|
\\const a = foo{ .x = 1, .y = 2 };
|
|
\\const a = foo{
|
|
\\ .x = 1,
|
|
\\ .y = 2,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: multiline string with backslash at end of line" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ err(
|
|
\\ \\\
|
|
\\ );
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: multiline string parameter in fn call with trailing comma" {
|
|
try testCanonical(
|
|
\\fn foo() void {
|
|
\\ try stdout.print(
|
|
\\ \\ZIG_CMAKE_BINARY_DIR {s}
|
|
\\ \\ZIG_C_HEADER_FILES {s}
|
|
\\ \\ZIG_DIA_GUIDS_LIB {s}
|
|
\\ \\
|
|
\\ ,
|
|
\\ std.mem.sliceTo(c.ZIG_CMAKE_BINARY_DIR, 0),
|
|
\\ std.mem.sliceTo(c.ZIG_CXX_COMPILER, 0),
|
|
\\ std.mem.sliceTo(c.ZIG_DIA_GUIDS_LIB, 0),
|
|
\\ );
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: trailing comma on fn call" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ var module = try Module.create(
|
|
\\ allocator,
|
|
\\ zig_lib_dir,
|
|
\\ full_cache_dir,
|
|
\\ );
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: multi line arguments without last comma" {
|
|
try testTransform(
|
|
\\pub fn foo(
|
|
\\ a: usize,
|
|
\\ b: usize,
|
|
\\ c: usize,
|
|
\\ d: usize
|
|
\\) usize {
|
|
\\ return a + b + c + d;
|
|
\\}
|
|
\\
|
|
,
|
|
\\pub fn foo(a: usize, b: usize, c: usize, d: usize) usize {
|
|
\\ return a + b + c + d;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: empty block with only comment" {
|
|
try testCanonical(
|
|
\\comptime {
|
|
\\ {
|
|
\\ // comment
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: trailing commas on struct decl" {
|
|
try testTransform(
|
|
\\const RoundParam = struct {
|
|
\\ k: usize, s: u32, t: u32
|
|
\\};
|
|
\\const RoundParam = struct {
|
|
\\ k: usize, s: u32, t: u32,
|
|
\\};
|
|
,
|
|
\\const RoundParam = struct { k: usize, s: u32, t: u32 };
|
|
\\const RoundParam = struct {
|
|
\\ k: usize,
|
|
\\ s: u32,
|
|
\\ t: u32,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: extra newlines at the end" {
|
|
try testTransform(
|
|
\\const a = b;
|
|
\\
|
|
\\
|
|
\\
|
|
,
|
|
\\const a = b;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: nested struct literal with one item" {
|
|
try testCanonical(
|
|
\\const a = foo{
|
|
\\ .item = bar{ .a = b },
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: block with same line comment after end brace" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ {
|
|
\\ const a = b;
|
|
\\ } // end of block
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comments before var decl in struct" {
|
|
try testCanonical(
|
|
\\const Foo = struct {
|
|
\\ /// comment
|
|
\\ bar: bool = true,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comments before global variables" {
|
|
try testCanonical(
|
|
\\/// comment
|
|
\\var foo: i32 = undefined;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comments before test decl" {
|
|
try testCanonical(
|
|
\\/// top level doc comment
|
|
\\test "hi" {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: alignment" {
|
|
try testCanonical(
|
|
\\var foo: c_int align(1);
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: C main" {
|
|
try testCanonical(
|
|
\\fn main(argc: c_int, argv: **u8) c_int {
|
|
\\ const a = b;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: return" {
|
|
try testCanonical(
|
|
\\fn foo(argc: c_int, argv: **u8) c_int {
|
|
\\ return 0;
|
|
\\}
|
|
\\
|
|
\\fn bar() void {
|
|
\\ return;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: 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: arrays" {
|
|
try testCanonical(
|
|
\\test "arrays" {
|
|
\\ const a: [2]u32 = .{ 1, 2 };
|
|
\\ const b = a ++ a;
|
|
\\ const c = a[0..];
|
|
\\ _ = c;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container initializers" {
|
|
try testCanonical(
|
|
\\const a0 = []u8{};
|
|
\\const a1 = []u8{1};
|
|
\\const a2 = []u8{
|
|
\\ 1,
|
|
\\ 2,
|
|
\\ 3,
|
|
\\ 4,
|
|
\\};
|
|
\\const s0 = S{};
|
|
\\const s1 = S{ .a = 1 };
|
|
\\const s2 = S{
|
|
\\ .a = 1,
|
|
\\ .b = 2,
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: blocks" {
|
|
try testCanonical(
|
|
\\test {
|
|
\\ {
|
|
\\ const a = b;
|
|
\\ }
|
|
\\ const c = d;
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: defer" {
|
|
try testCanonical(
|
|
\\test "defer" {
|
|
\\ defer foo();
|
|
\\ defer {
|
|
\\ bar();
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comptime" {
|
|
try testCanonical(
|
|
\\fn foo() void {
|
|
\\ comptime {
|
|
\\ bar();
|
|
\\ }
|
|
\\}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comptime block in container" {
|
|
try testCanonical(
|
|
\\const Foo = struct {
|
|
\\ comptime {
|
|
\\ @compileLog("hello comptime");
|
|
\\ }
|
|
\\};
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comment after empty comment" {
|
|
try testCanonical(
|
|
\\//
|
|
\\/// A doc comment
|
|
\\const a = b;
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: comment after params" {
|
|
try testCanonical(
|
|
\\fn foo(
|
|
\\ a: i32, // comment
|
|
\\ b: i32, // comment
|
|
\\) void {}
|
|
\\
|
|
);
|
|
}
|
|
|
|
test "zig fmt: container doc comments" {
|
|
try testCanonical(
|
|
\\//! tld 1
|
|
\\//! tld 2
|
|
\\//! tld 3
|
|
\\const a = b;
|
|
\\
|
|
);
|
|
}
|
|
|
|
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 "Ast header smoke test" {
|
|
try std.testing.expectEqual(zigNode(c.AST_NODE_IF), Ast.Node.Tag.@"if");
|
|
}
|
|
|
|
test "my function" {
|
|
try testCanonical(
|
|
\\pub fn main() void {
|
|
\\ @panic("hello");
|
|
\\}
|
|
\\
|
|
);
|
|
}
|