Comentários e documentação
Nesta aula, você aprenderá a usar comentários de linha e bloco, documentação com doc comments (///), geração de documentação com cargo doc e exemplos testáveis em Rust. Essas ferramentas são essenciais para escrever código claro e bem documentado.
Comentários e documentação são fundamentais para a legibilidade e manutenção do código. Em Rust, existem diferentes tipos de comentários: os comentários de linha e bloco, que são ignorados pelo compilador, e os doc comments, que geram documentação automaticamente. Além disso, o Rust oferece a ferramenta cargo doc para gerar documentação HTML a partir dos doc comments, e suporte a exemplos testáveis que garantem que a documentação esteja sempre atualizada.
Nesta aula, exploraremos cada um desses tópicos em detalhes, com exemplos práticos e boas práticas.
Comentários de linha e bloco
Comentários são trechos de texto no código que são ignorados pelo compilador. Eles servem para explicar o propósito de partes do código, deixar notas ou desabilitar temporariamente blocos de código. Em Rust, há dois tipos principais: comentários de linha e comentários de bloco.
Os comentários de linha começam com // e se estendem até o final da linha. São usados para comentários curtos ou explicações rápidas. Já os comentários de bloco começam com /* e terminam com */, podendo abranger múltiplas linhas. São úteis para comentários mais longos ou para desabilitar trechos de código.
// Este é um comentário de linha
/*
* Este é um comentário de bloco
* que pode ter várias linhas
*/
fn main() {
// Comentário explicando a próxima linha
let x = 42; // Comentário no final da linha
/*
* Bloco de código desabilitado:
* println!("Isso não será executado");
*/
println!("x = {}", x);
}É importante lembrar que comentários de bloco podem ser aninhados? Em Rust, eles não podem ser aninhados, ou seja, você não pode colocar um /* dentro de outro /* */. Por isso, para comentar grandes blocos de código que já contenham comentários de bloco, prefira usar // no início de cada linha ou usar a ferramenta cargo com #[cfg(comment)].
Doc comments (///)
Doc comments são um tipo especial de comentário que gera documentação para o código. Eles são escritos com três barras /// para documentar itens (funções, structs, módulos, etc.) e são processados pelo comando cargo doc para gerar páginas HTML. Além disso, suportam Markdown para formatação e podem incluir exemplos de código.
/// Soma dois números inteiros.
///
/// # Exemplos
///
/// ```
/// let resultado = soma(2, 3);
/// assert_eq!(resultado, 5);
/// ```
pub fn soma(a: i32, b: i32) -> i32 {
a + b
}Os doc comments também podem ser usados com //! para documentar o item que os contém (como um módulo ou crate). Eles são colocados no início do arquivo ou dentro do módulo. Por exemplo:
//! # Meu Crate
//!
//! Esta é a documentação do crate.É uma boa prática documentar todas as funções públicas, structs e módulos com doc comments, explicando o propósito, parâmetros, retorno e possíveis panics. O Rustacean (comunidade Rust) valoriza muito a documentação.
cargo doc
O comando cargo doc gera documentação HTML a partir dos doc comments do seu projeto. Ele usa o rustdoc internamente e produz uma página de documentação que pode ser visualizada no navegador. Para gerar e abrir a documentação, use:
cargo doc --openIsso criará uma pasta target/doc com toda a documentação do seu crate e das dependências. A documentação inclui links para tipos, funções e módulos, além de exemplos testáveis. Você também pode gerar documentação apenas para o seu crate com cargo doc --no-deps.
A documentação gerada é estática e pode ser hospedada em serviços como docs.rs. O docs.rs é o principal repositório de documentação de crates Rust, e ele automaticamente gera e hospeda a documentação de cada versão de crate publicada no crates.io.
Algumas opções úteis do cargo doc:
--open: abre a documentação no navegador após gerar.--no-deps: gera apenas a documentação do seu crate, ignorando dependências.--document-private-items: inclui itens privados na documentação.
Exemplos testáveis
Os exemplos em doc comments podem ser testáveis, ou seja, o Rust pode compilar e executar o código dos exemplos para garantir que estejam corretos. Para criar um exemplo testável, basta escrever um bloco de código Markdown com três crases e a linguagem rust (ou omitir a linguagem, que o padrão é rust). O comando cargo test executará todos os exemplos de documentação (doctests) e reportará falhas.
/// Divide dois números.
///
/// # Exemplos
///
/// ```
/// let resultado = divide(10, 2);
/// assert_eq!(resultado, 5);
/// ```
///
/// ```rust,should_panic
/// // Este exemplo deve causar pânico
/// divide(1, 0);
/// ```
pub fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
panic!("Divisão por zero");
}
a / b
}Você pode usar atributos como should_panic, no_run, ignore e compile_fail para controlar o comportamento do teste. Por exemplo, ```rust,should_panic indica que o código deve causar pânico, e o teste passará se isso ocorrer. ```rust,no_run compila mas não executa, útil para exemplos que não podem ser executados (como código que depende de hardware).
Os exemplos testáveis são uma excelente forma de manter a documentação atualizada e garantir que os exemplos funcionem como esperado. Sempre que possível, inclua exemplos testáveis nas suas doc comments.
Boas práticas e observações finais
- Use comentários de linha (
//) para explicações breves e comentários de bloco (/* */) para desabilitar código ou comentários longos. - Documente todas as funções e tipos públicos com doc comments (
///). - Inclua seções como
# Exemplos,# Panics,# Errorse# Safetynos doc comments para clareza. - Execute
cargo doc --openregularmente para visualizar a documentação gerada. - Use exemplos testáveis para garantir que a documentação esteja correta e funcional.
Referências
- The Rust Programming Language - Comments
- Rust Documentation Tool (rustdoc)
- Cargo doc command
- Documentation tests
- The doc attribute
- docs.rs: documentation host
Exercícios
Escreva uma função pública chamada
saudacaoque recebe um nome e retorna uma string de saudação. Adicione um doc comment completo com descrição e um exemplo testável.✓ Resposta:/// Retorna uma saudação personalizada. /// /// # Exemplos /// /// ``` /// let msg = saudacao("Mundo"); /// assert_eq!(msg, "Olá, Mundo!"); /// ``` pub fn saudacao(nome: &str) -> String { format!("Olá, {}!", nome) }Adicione um comentário de linha e um comentário de bloco no código abaixo. O comentário de linha deve explicar a variável
x, e o comentário de bloco deve desabilitar a linhaprintln!("Isso não deve ser executado");.fn main() { let x = 10; println!("x = {}", x); println!("Isso não deve ser executado"); }✓ Resposta:fn main() { // x é uma variável inteira com valor 10 let x = 10; println!("x = {}", x); /* println!("Isso não deve ser executado"); */ }Gere a documentação do seguinte código usando
cargo doc. Explique o que o comando faz e qual arquivo é gerado./// Retorna o quadrado de um número. pub fn quadrado(x: i32) -> i32 { x * x }✓ Resposta:O comando
cargo doc --opengera a documentação HTML a partir dos doc comments. A documentação é salva emtarget/doc/nome_do_crate/index.htmle aberta no navegador. A página mostra a funçãoquadradocom seu doc comment.Crie um exemplo testável que deve falhar (compile_fail) no doc comment de uma função que só aceita números positivos. A função deve usar um tipo que garanta isso (ex:
u32).✓ Resposta:/// Retorna o dobro de um número positivo. /// /// # Exemplos /// /// ``` /// let resultado = dobro(5u32); /// assert_eq!(resultado, 10); /// ``` /// /// ```rust,compile_fail /// // Isto não compila porque passamos um número negativo /// let resultado = dobro(-5u32); /// ``` pub fn dobro(x: u32) -> u32 { x * 2 }Escreva um doc comment para a função abaixo que inclua as seções
# Panicse# Exemplos. A função deve entrar em pânico se o índice for maior que o tamanho do vetor.pub fn elemento(v: &[i32], indice: usize) -> i32 { if indice >= v.len() { panic!("Índice fora dos limites"); } v[indice] }✓ Resposta:/// Retorna o elemento de um vetor no índice especificado. /// /// # Panics /// /// A função entrará em pânico se o índice for maior ou igual ao comprimento do vetor. /// /// # Exemplos /// /// ``` /// let v = vec![10, 20, 30]; /// assert_eq!(elemento(&v, 1), 20); /// ``` /// /// ```rust,should_panic /// let v = vec![10]; /// elemento(&v, 5); // Isto causa pânico /// ``` pub fn elemento(v: &[i32], indice: usize) -> i32 { if indice >= v.len() { panic!("Índice fora dos limites"); } v[indice] }