在宏中生成文档
Generating documentation in macros
在定义某些形式的元组结构时,我有几个宏可以减少样板代码:
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
。剩下的唯一选择是在宏中编写非常通用的文档,但这会导致我的库的文档记录比它可能的要糟糕得多。
您对处理此问题有何建议?对我来说最好的解决方案是能够为每个宏调用编写特定的文档,但如果这不可能,我将不胜感激关于如何在文档注释中扩展标记的提示。
可以在宏调用中捕获文档注释。它并不广为人知,但 Rust 文档实际上表示为项目的一种特殊属性。例如:
/// Some documentation comment
pub fn function() {}
// is equivalent to
#[doc="Some documentation comment"]
pub fn function() {}
并且可以在宏中捕获属性。已经有几个使用此功能的宏,最常用的可能是 bitflags!
:
macro_rules! bitflags {
(
$(#[$outer:meta])*
pub struct $BitFlags:ident: $T:ty {
$(
$(#[$inner:ident $($args:tt)*])*
const $Flag:ident = $value:expr;
)+
}
) => { /* ... */ };
// ...
}
注意模式的 $(#[$outer:meta])*
和 $(#[$inner:meta])*
部分。这些捕获放置在模式中相应项目之前的所有属性。如果你在那里写一个文档注释,它将被转换为 doc 属性,并像往常一样传递给 rustdoc。
以下是来自 quick_error
crate 的示例,它也使用了这种方法:
quick_error! {
#[derive(Debug)]
pub enum SomeError {
/// IO Error
Io(err: io::Error) {}
/// Arbitrary system error
Sys(errno: nix::Errno) {}
}
}
它确实有效——here is an example of the structure generated by quick_error
macro, and here 是它的定义。
在定义某些形式的元组结构时,我有几个宏可以减少样板代码:
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
。剩下的唯一选择是在宏中编写非常通用的文档,但这会导致我的库的文档记录比它可能的要糟糕得多。
您对处理此问题有何建议?对我来说最好的解决方案是能够为每个宏调用编写特定的文档,但如果这不可能,我将不胜感激关于如何在文档注释中扩展标记的提示。
可以在宏调用中捕获文档注释。它并不广为人知,但 Rust 文档实际上表示为项目的一种特殊属性。例如:
/// Some documentation comment
pub fn function() {}
// is equivalent to
#[doc="Some documentation comment"]
pub fn function() {}
并且可以在宏中捕获属性。已经有几个使用此功能的宏,最常用的可能是 bitflags!
:
macro_rules! bitflags {
(
$(#[$outer:meta])*
pub struct $BitFlags:ident: $T:ty {
$(
$(#[$inner:ident $($args:tt)*])*
const $Flag:ident = $value:expr;
)+
}
) => { /* ... */ };
// ...
}
注意模式的 $(#[$outer:meta])*
和 $(#[$inner:meta])*
部分。这些捕获放置在模式中相应项目之前的所有属性。如果你在那里写一个文档注释,它将被转换为 doc 属性,并像往常一样传递给 rustdoc。
以下是来自 quick_error
crate 的示例,它也使用了这种方法:
quick_error! {
#[derive(Debug)]
pub enum SomeError {
/// IO Error
Io(err: io::Error) {}
/// Arbitrary system error
Sys(errno: nix::Errno) {}
}
}
它确实有效——here is an example of the structure generated by quick_error
macro, and here 是它的定义。