Документирование Rust проекта: полное руководство от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Почему документация в Rust — это не роскошь, а необходимость

Rust славится своей безопасной работой с памятью, производительностью и строгой системой типов. Однако даже самый элегантный код бесполезен, если никто не понимает, как его использовать. Качественная документация — это мост между вашим кодом и пользователями (включая вас самих через полгода).

К счастью, в Rust заложены мощные инструменты для автоматической генерации документации прямо из исходного кода. В этой статье мы разберём весь процесс: от простых комментариев до создания полноценной документации с примерами, ссылками и даже математическими формулами.

1. Основы: doc-комментарии и rustdoc

В Rust существует два типа комментариев: обычные (// и /* */) и документационные (/// и //!). Последние обрабатываются утилитой rustdoc, которая генерирует HTML-документацию.

1.1. Внешние и внутренние doc-комментарии

  • /// — внешний комментарий. Пишется перед элементом (функцией, структурой, трейтом) и описывает его.
  • //! — внутренний комментарий. Используется для документирования самого модуля, крейта или файла.
/// Вычисляет факториал числа n.
///
/// # Примеры
/// ```
/// let result = factorial(5);
/// assert_eq!(result, 120);
/// ```
pub fn factorial(n: u32) -> u32 {
    (1..=n).product()
}

//! # Мой супер-крейт
//!
//! Этот крейт предоставляет утилиты для работы с математикой.
//! Подробнее смотрите в [документации](https://example.com).

1.2. Запуск генерации документации

Чтобы сгенерировать документацию, выполните команду:

cargo doc --open

Эта команда просканирует все doc-комментарии в вашем проекте, создаст HTML-файлы в папке target/doc/ и откроет их в браузере. Вы увидите страницу со списком модулей, функций и структур — всё, как на docs.rs.

2. Секции документации: как сделать её читаемой

Просто написать комментарий недостаточно. Чтобы документация была полезной, её нужно структурировать. rustdoc поддерживает Markdown, поэтому вы можете использовать заголовки, списки, ссылки и даже блоки кода.

2.1. Стандартные секции

Принято использовать следующие секции (начинаются с # ):

  • # Examples — один или несколько примеров использования.
  • # Panics — в каких случаях функция вызывает панику.
  • # Errors — если функция возвращает Result, опишите возможные ошибки.
  • # Safety — обязательна для unsafe функций.
  • # Arguments — описание параметров (хотя часто их описывают прямо в тексте).
/// Читает содержимое файла и возвращает его как строку.
///
/// # Arguments
/// * `path` — путь к файлу.
///
/// # Errors
/// Возвращает `io::Error`, если файл не существует или недоступен для чтения.
///
/// # Panics
/// Паникует, если путь содержит нулевой байт.
///
/// # Examples
/// ```
/// let content = read_file("hello.txt").unwrap();
/// println!("{}", content);
/// ```
pub fn read_file(path: &str) -> Result<String, std::io::Error> {
    std::fs::read_to_string(path)
}

2.2. Ссылки и перекрёстные ссылки

Вы можете ссылаться на другие элементы кода. rustdoc автоматически превратит их в гиперссылки:

/// Использует функцию [`factorial`] для вычисления комбинаций.
/// См. также модуль [`math::combinatorics`].
pub fn combinations(n: u32, k: u32) -> u32 {
    factorial(n) / (factorial(k) * factorial(n - k))
}

Если нужно сослаться на внешний крейт, используйте полный путь, например [`std::fs::read_to_string`].

3. Тестирование документации: примеры как тесты

Одна из лучших фич Rust — примеры кода в документации автоматически компилируются и запускаются как тесты! Это гарантирует, что ваша документация не устаревает.

3.1. Запуск тестов документации

Чтобы проверить все примеры в документации, выполните:

cargo test --doc

Если пример содержит ошибку, тест упадёт, и вы узнаете об этом до того, как документация попадёт к пользователям.

3.2. Скрытие кода от тестов

Иногда нужно показать код, который не должен компилироваться (например, пример с ошибкой). Используйте атрибут ignore:

/// ```ignore
/// // Этот код не компилируется, но показывает идею
/// let x: u32 = -1; // Ошибка!
/// ```

Или no_run, если код компилируется, но не должен запускаться (например, бесконечный цикл):

/// ```no_run
/// loop {
///     println!("Бесконечность!");
/// }
/// ```

3.3. Пример с ожидаемым результатом

Вы можете использовать assert_eq! внутри примеров, чтобы явно показать ожидаемый вывод:

/// ```
/// let result = add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

4. Продвинутые техники: атрибуты, скрытие и кастомизация

4.1. Атрибуты документации

Вы можете управлять поведением rustdoc с помощью атрибутов: