Генерация документации в макросах
У меня есть пара макросов, чтобы уменьшить шаблон при определении определенных структур кортежа формы:
macro_rules! new_type (($name:ident, $bytes:expr) => (
pub struct $name(pub [u8; $bytes]);
// some common operations on $name
));
Однако я также хотел бы задокументировать эти новые структуры. Лучше всего было бы, если бы я мог написать свою документацию прямо перед вызовом макроса.
/// A certain type
new_type!(CertainType, 42);
Однако Rust не будет генерировать документацию для CertainType
когда это произойдет.
Другой (не такой гибкой) альтернативой было бы сделать что-то вроде:
macro_rules! new_type (($name:ident, $bytes:expr) => (
/// Some more generic documentation for $name
pub struct $name(pub [u8; $bytes]);
// some common operations on $name
));
Однако при этом макрос-система Rust не расширяет токен $name
в комментарии к документации. Единственная альтернатива - написать очень общую документацию в макросе, но это приведет к тому, что моя библиотека будет документирована намного хуже, чем могла бы быть.
Каковы ваши рекомендации по обращению с этим? Лучшее решение для меня - написать конкретную документацию для каждого вызова макроса, но если это невозможно, я буду благодарен за подсказки о том, как расширить токены в комментариях к документации.
1 ответ
Возможно захватить комментарии документа в вызовах макроса. Он не очень широко известен, но документация Rust фактически представляется как особый вид атрибута для элемента. Например:
/// Some documentation comment
pub fn function() {}
// is equivalent to
#[doc="Some documentation comment"]
pub fn function() {}
И можно захватывать атрибуты в макросах. Уже есть несколько макросов, которые используют эту способность, наиболее часто используемым bitflags!
:
macro_rules! bitflags {
($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
$($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+
}) =>
...
}
Обратите внимание $(#[$attr:meta])*
часть шаблона. Он захватывает все атрибуты, помещенные перед соответствующим элементом в шаблоне. Если вы напишете там комментарий к документу, он будет фактически преобразован в атрибут документа и будет передан rustdoc, как обычно. Ниже приведен пример из quick_error
ящик, который также использует этот подход:
quick_error! {
#[derive(Debug)]
pub enum SomeError {
/// IO Error
Io(err: io::Error) {}
/// Arbitrary system error
Sys(errno: nix::Errno) {}
}
}
и это работает - вот пример структуры, генерируемой quick_error
макрос, и вот его определение.