In this lesson, you will learn how to ensure that code generated by your macros is properly documented and discoverable by rustdoc.
When you write a procedural macro that generates trait implementations or public methods, those items are often "invisible" to documentation generators because they are synthesized at compile time. By default, rustdoc doesn't know how to look inside the TokenStream to extract doc comments.
Using doc Attributes
To make your generated code appear in the final documentation, you must explicitly emit #[doc = "..."] attributes into the generated TokenStream. Since macros output raw tokens, you can use the quote! macro to inject these attributes just as you would any other piece of code.
Consider a derive macro that adds a helper method:
use quote::quote;
pub fn generate_doc_wrapper(name: &syn::Ident) -> proc_macro2::TokenStream {
let doc_str = format!("Generated documentation for trait implementation on {}.", name);
quote! {
impl #name {
#[doc = #doc_str]
pub fn generated_method(&self) {
// implementation
}
}
}
}
Best Practices for Macro Documentation
When generating documentation, follow these three rules:
- Format Dynamically: Use
format!inside your procedural macro to construct context-aware doc strings (like referencing the struct name or the field type). - Use
#[doc = ...]over///: Because procedural macros deal withTokenStreamobjects, standard///comments are often parsed as syntax nodes that the compiler might struggle to attach to the correct item. The#[doc = "..."]syntax is a direct attribute that is much more robust to inject programmatically. - Include Usage Examples: If your macro adds a significant trait, generate a
DocTestblock by including#[doc = "```"]lines in your attribute string to ensure your macro's output remains compliant with the user's expectations.
By programmatically injecting these attributes, you transform your generated code from an opaque "black box" into a well-documented API that integrates seamlessly with the rest of the crate's documentation.
Key Takeaway: Use the #[doc = "..."] attribute within your quote! blocks to ensure that synthesized items are captured and rendered by rustdoc.