Ferramentas de Documentação em Zig — Geradores e Boas Práticas

Ferramentas de Documentação em Zig — Geradores e Boas Práticas

Documentação de qualidade é essencial para a adoção e manutenção de qualquer projeto. O Zig inclui um sistema de documentação integrado ao compilador que gera documentação HTML automaticamente a partir de comentários no código fonte. Este guia cobre o sistema nativo, ferramentas de terceiros e boas práticas para documentar projetos Zig.

Autodoc — Documentação Integrada

O compilador Zig inclui o zig doc, uma ferramenta que gera documentação HTML a partir de doc comments no código:

# Gerar documentação
zig doc src/lib.zig

# Servir documentação localmente
zig doc --listen 8080 src/lib.zig

Doc Comments

O Zig usa /// para doc comments (documentação pública) e //! para documentação de módulo:

//! # Módulo de Criptografia
//!
//! Este módulo fornece implementações seguras de algoritmos
//! criptográficos para uso em aplicações Zig.
//!
//! ## Exemplo de Uso
//!
//! ```zig
//! const crypto = @import("crypto");
//! var hash: [32]u8 = undefined;
//! crypto.sha256("dados", &hash);
//! ```

const std = @import("std");

/// Calcula o hash SHA-256 de um bloco de dados.
///
/// ## Parâmetros
///
/// - `dados`: Slice de bytes a ser hasheado
/// - `resultado`: Buffer de 32 bytes para armazenar o hash
///
/// ## Exemplo
///
/// ```zig
/// var hash: [32]u8 = undefined;
/// sha256("mensagem secreta", &hash);
/// ```
///
/// ## Notas de Segurança
///
/// Esta implementação opera em tempo constante para evitar
/// ataques de side-channel.
pub fn sha256(dados: []const u8, resultado: *[32]u8) void {
    std.crypto.hash.sha2.Sha256.hash(dados, resultado, .{});
}

/// Representa uma conexão segura TLS com um servidor remoto.
///
/// Use `init()` para criar uma nova conexão e `deinit()` para
/// liberar recursos. A conexão implementa a interface `Reader`
/// e `Writer` da std.
///
/// ## Lifecycle
///
/// 1. Criar com `SecureConnection.init()`
/// 2. Conectar com `.connect()`
/// 3. Ler/escrever com `.reader()` e `.writer()`
/// 4. Fechar com `.deinit()`
pub const SecureConnection = struct {
    /// O endereço do servidor remoto.
    host: []const u8,

    /// A porta de conexão (padrão: 443).
    port: u16 = 443,

    /// Indicador de estado da conexão.
    connected: bool = false,

    /// Inicializa uma nova conexão segura.
    ///
    /// O `allocator` é usado para buffers internos e será
    /// liberado em `deinit()`.
    pub fn init(allocator: std.mem.Allocator, host: []const u8) !SecureConnection {
        _ = allocator;
        return SecureConnection{
            .host = host,
        };
    }

    /// Libera todos os recursos da conexão.
    ///
    /// Após chamar `deinit()`, a conexão não pode ser reutilizada.
    pub fn deinit(self: *SecureConnection) void {
        self.connected = false;
    }
};

/// Erros que podem ocorrer durante operações criptográficas.
pub const CryptoError = error{
    /// O tamanho da chave não corresponde ao esperado pelo algoritmo.
    InvalidKeySize,

    /// O nonce fornecido já foi utilizado anteriormente.
    NonceReuse,

    /// A verificação de autenticidade do dado cifrado falhou.
    AuthenticationFailed,

    /// O buffer de saída é pequeno demais para o resultado.
    BufferTooSmall,
};

Markdown em Doc Comments

Os doc comments suportam um subconjunto de Markdown:

/// # Título Principal
///
/// ## Subtítulo
///
/// Texto normal com **negrito** e *itálico*.
///
/// ### Listas
///
/// - Item 1
/// - Item 2
///   - Sub-item
///
/// ### Código
///
/// ```zig
/// const x = 42;
/// ```
///
/// ### Links
///
/// Veja também `outra_funcao` e `MeuTipo`.
///
/// ### Tabelas
///
/// | Coluna 1 | Coluna 2 |
/// |----------|----------|
/// | Valor A  | Valor B  |
pub fn funcaoDocumentada() void {}

Integração com build.zig

Step de Documentação

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // Biblioteca principal
    const lib = b.addStaticLibrary(.{
        .name = "minha-lib",
        .root_source_file = b.path("src/lib.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Step de documentação
    const docs = b.addStaticLibrary(.{
        .name = "minha-lib",
        .root_source_file = b.path("src/lib.zig"),
        .target = target,
        .optimize = optimize,
    });

    const install_docs = b.addInstallDirectory(.{
        .source = docs.getEmittedDocs(),
        .install_dir = .prefix,
        .install_subdir = "docs",
    });

    const doc_step = b.step("docs", "Gerar documentação HTML");
    doc_step.dependOn(&install_docs.step);

    b.installArtifact(lib);
}
# Gerar documentação
zig build docs

# Documentação estará em zig-out/docs/

Documentação de API Pública

Padrões Recomendados

/// Servidor HTTP de alta performance.
///
/// O `HttpServer` gerencia conexões TCP, parsing de requisições
/// e roteamento para handlers registrados. Suporta HTTP/1.1
/// com keep-alive e compressão gzip.
///
/// ## Exemplo Rápido
///
/// ```zig
/// var server = try HttpServer.init(allocator, .{ .port = 8080 });
/// defer server.deinit();
///
/// server.get("/", handleHome);
/// server.get("/api/users", handleUsers);
///
/// try server.listen();
/// ```
///
/// ## Thread Safety
///
/// O servidor é thread-safe e pode processar múltiplas
/// requisições simultaneamente usando um pool de threads.
///
/// ## Veja Também
///
/// - `Router` para configuração avançada de rotas
/// - `Middleware` para interceptação de requisições
/// - `Response` para construção de respostas
pub const HttpServer = struct {
    // ...
};

Documentando Erros

/// Abre e analisa um arquivo de configuração TOML.
///
/// ## Parâmetros
///
/// - `caminho`: Caminho absoluto ou relativo ao arquivo
/// - `allocator`: Alocador para strings e estruturas internas
///
/// ## Retorno
///
/// Retorna uma struct `Config` com todos os campos populados.
///
/// ## Erros
///
/// - `error.FileNotFound`: O arquivo não existe no caminho especificado
/// - `error.ParseError`: O conteúdo não é TOML válido
/// - `error.OutOfMemory`: Memória insuficiente para parsing
///
/// ## Exemplo
///
/// ```zig
/// const config = carregarConfig("config.toml", allocator) catch |err| {
///     log.err("Falha ao carregar config: {}", .{err});
///     return err;
/// };
/// ```
pub fn carregarConfig(caminho: []const u8, allocator: std.mem.Allocator) !Config {
    // ...
}

Ferramentas de Terceiros

zig-doctest

Executa exemplos de código nos doc comments como testes:

# Verificar que todos os exemplos compilam e executam
zig-doctest src/lib.zig

zigdoc.org

Portal online para documentação de pacotes Zig publicados, semelhante ao docs.rs para Rust.

Boas Práticas

  1. Documente a API pública: Todo pub fn, pub const e pub const struct deve ter doc comment
  2. Inclua exemplos: Exemplos de código nos doc comments são a melhor documentação
  3. Documente erros: Liste todos os erros possíveis e suas causas
  4. Use doc comments de módulo: //! no topo do arquivo para visão geral
  5. Mantenha doc comments atualizados: Documentação desatualizada é pior que nenhuma
  6. Gere docs no CI: Automatize a geração e publicação de documentação

Próximos Passos

Explore os frameworks de teste para validar exemplos de documentação, o ZLS para preview de docs no editor, e os plugins IDE para melhor visualização. Consulte nossos tutoriais para exemplos de projetos bem documentados.

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.