patternrustMajor
Generating documentation in macros
Viewed 0 times
documentationmacrosgenerating
Problem
I have a couple of macros to reduce boilerplate when defining certain tuple-structs of the form:
However, I would also like to document these new structs. The best thing would be if I could write my documentation right before my macro invocation.
However, Rust won't generate documentation for
Another (not as flexible) alternative would be to do something like:
However, when doing that the Rust macro system doesn't expand the token
What are your recommendations for handling this? The best solution for me would be to be able to write specific documentation for each macro invocation, but if that's not possible I would be grateful for hints on how to expand tokens in documentation comments.
macro_rules! new_type (($name:ident, $bytes:expr) => (
pub struct $name(pub [u8; $bytes]);
// some common operations on $name
));However, I would also like to document these new structs. The best thing would be if I could write my documentation right before my macro invocation.
/// A certain type
new_type!(CertainType, 42);However, Rust won't generate documentation for
CertainType when this happens.Another (not as flexible) alternative would be to do something like:
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
));However, when doing that the Rust macro system doesn't expand the token
$name in the documentation comment. The only alternative left is to write very generic documentation in the macro, but that would lead to my library being a lot worse documented than it could be.What are your recommendations for handling this? The best solution for me would be to be able to write specific documentation for each macro invocation, but if that's not possible I would be grateful for hints on how to expand tokens in documentation comments.
Solution
It is possible to capture doc comments in macro invocations. It is not widely-known, but Rust documentation is actually represented as a special kind of attribute on an item. For example:
And it is possible to capture attributes in macros. There are already several macros which use this ability, the most used probably being
Note the
The following is an example from the
It does work — here is an example of the structure generated by
/// Some documentation comment
pub fn function() {}
// is equivalent to
#[doc="Some documentation comment"]
pub fn function() {}And it is possible to capture attributes in macros. There are already several macros which use this ability, the most used probably being
bitflags!:macro_rules! bitflags {
(
$(#[$outer:meta])*
pub struct $BitFlags:ident: $T:ty {
$(
$(#[$inner:ident $($args:tt)*])*
const $Flag:ident = $value:expr;
)+
}
) => { /* ... */ };
// ...
}Note the
$(#[$outer:meta]) and $(#[$inner:meta]) parts of the pattern. These capture all attributes placed before the respective item in the pattern. If you write a doc comment there, it will be converted to the doc attribute and will be passed to rustdoc, as usual.The following is an example from the
quick_error crate which also uses this approach:quick_error! {
#[derive(Debug)]
pub enum SomeError {
/// IO Error
Io(err: io::Error) {}
/// Arbitrary system error
Sys(errno: nix::Errno) {}
}
}It does work — here is an example of the structure generated by
quick_error macro, and here is its definition.Code Snippets
/// Some documentation comment
pub fn function() {}
// is equivalent to
#[doc="Some documentation comment"]
pub fn function() {}macro_rules! bitflags {
(
$(#[$outer:meta])*
pub struct $BitFlags:ident: $T:ty {
$(
$(#[$inner:ident $($args:tt)*])*
const $Flag:ident = $value:expr;
)+
}
) => { /* ... */ };
// ...
}quick_error! {
#[derive(Debug)]
pub enum SomeError {
/// IO Error
Io(err: io::Error) {}
/// Arbitrary system error
Sys(errno: nix::Errno) {}
}
}Context
Stack Overflow Q#33999341, score: 78
Revisions (0)
No revisions yet.