Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

renderContainer

ast.renderContainer
fn renderContainer(c: *Context, node: Node) !NodeIndex

File

Code

fn renderContainer(c: *Context, node: Node) !NodeIndex {
    const payload = @as(*Payload.Container, @alignCast(@fieldParentPtr("base", node.ptr_otherwise))).data;
    if (payload.layout == .@"packed")
        _ = try c.addToken(.keyword_packed, "packed")
    else if (payload.layout == .@"extern")
        _ = try c.addToken(.keyword_extern, "extern");
    const kind_tok = if (node.tag() == .@"struct")
        try c.addToken(.keyword_struct, "struct")
    else if (node.tag() == .@"union")
        try c.addToken(.keyword_union, "union")
    else if (node.tag() == .@"opaque")
        try c.addToken(.keyword_opaque, "opaque")
    else
        unreachable;

    _ = try c.addToken(.l_brace, "{");

    const num_decls = payload.decls.len;
    const total_members = payload.fields.len + num_decls;
    const members = try c.gpa.alloc(NodeIndex, total_members);
    defer c.gpa.free(members);

    for (payload.fields, 0..) |field, i| {
        const name_tok = try c.addTokenFmt(.identifier, "{f}", .{std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true })});
        _ = try c.addToken(.colon, ":");
        const type_expr = try renderNode(c, field.type);

        const align_expr_opt = if (field.alignment) |alignment| blk: {
            _ = try c.addToken(.keyword_align, "align");
            _ = try c.addToken(.l_paren, "(");
            const align_expr = try c.addNode(.{
                .tag = .number_literal,
                .main_token = try c.addTokenFmt(.number_literal, "{d}", .{alignment}),
                .data = undefined,
            });
            _ = try c.addToken(.r_paren, ")");
            break :blk align_expr;
        } else null;

        const value_expr_opt = if (field.default_value) |value| blk: {
            _ = try c.addToken(.equal, "=");
            break :blk try renderNode(c, value);
        } else null;

        if (align_expr_opt) |align_expr| {
            if (value_expr_opt) |value_expr| {
                members[i] = try c.addNode(.{
                    .tag = .container_field,
                    .main_token = name_tok,
                    .data = .{ .node_and_extra = .{
                        type_expr,
                        try c.addExtra(std.zig.Ast.Node.ContainerField{
                            .align_expr = align_expr,
                            .value_expr = value_expr,
                        }),
                    } },
                });
            } else {
                members[i] = try c.addNode(.{
                    .tag = .container_field_align,
                    .main_token = name_tok,
                    .data = .{ .node_and_node = .{
                        type_expr,
                        align_expr,
                    } },
                });
            }
        } else {
            members[i] = try c.addNode(.{
                .tag = .container_field_init,
                .main_token = name_tok,
                .data = .{ .node_and_opt_node = .{
                    type_expr,
                    .fromOptional(value_expr_opt),
                } },
            });
        }
        _ = try c.addToken(.comma, ",");
    }
    for (members[payload.fields.len..], payload.decls) |*member, decl| {
        member.* = try renderNode(c, decl);
    }
    const trailing = switch (c.tokens.items(.tag)[c.tokens.len - 1]) {
        .comma, .semicolon => true,
        else => false,
    };
    _ = try c.addToken(.r_brace, "}");

    if (total_members == 0) {
        return c.addNode(.{
            .tag = .container_decl_two,
            .main_token = kind_tok,
            .data = .{ .opt_node_and_opt_node = .{
                .none, .none,
            } },
        });
    } else if (total_members <= 2) {
        return c.addNode(.{
            .tag = if (trailing) .container_decl_two_trailing else .container_decl_two,
            .main_token = kind_tok,
            .data = .{ .opt_node_and_opt_node = .{
                if (members.len >= 1) members[0].toOptional() else .none,
                if (members.len >= 2) members[1].toOptional() else .none,
            } },
        });
    } else {
        const span = try c.listToSpan(members);
        return c.addNode(.{
            .tag = if (trailing) .container_decl_trailing else .container_decl,
            .main_token = kind_tok,
            .data = .{ .extra_range = span },
        });
    }
}