2015-11-30 9 views
15

Ho un paio di macro per ridurre boilerplate momento di definire alcune tuple-struct della forma:Generazione di documentazione nelle macro

macro_rules! new_type (($name:ident, $bytes:expr) => (
    pub struct $name(pub [u8; $bytes]); 
    // some common operations on $name 
)); 

Tuttavia, vorrei anche documentare queste nuove strutture. La cosa migliore sarebbe se potessi scrivere la mia documentazione subito prima della mia macro invocazione.

/// A certain type 
new_type!(CertainType, 42); 

Tuttavia, ruggine non genererà documentazione per CertainType quando questo accade.

Altro (non come flessibile) alternativa sarebbe quella di fare qualcosa di simile:

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 
)); 

Tuttavia, quando si fa che il sistema di macro ruggine non si espande il token $name nel commento documentazione. L'unica alternativa rimasta è scrivere una documentazione molto generica nella macro, ma ciò porterebbe a documentare la mia libreria molto peggio di quanto potrebbe essere.

Quali sono i tuoi consigli per la gestione di questo? La soluzione migliore per me sarebbe quella di essere in grado di scrivere documentazione specifica per ogni invocazione di macro, ma se ciò non fosse possibile sarei grato per suggerimenti su come espandere i token nei commenti della documentazione.

+0

La documentazione generata non ha valore informativo, perché è generata. creare una sezione nella documentazione che descriva il modello, ma non gonfiare la documentazione. – Arne

risposta

16

È possibile acquisire commenti di documenti in richiami di macro. Non è molto conosciuto, ma la documentazione di Rust è in realtà rappresentata come un tipo speciale di attributo su un oggetto. Per esempio:

/// Some documentation comment 
pub fn function() {} 

// is equivalent to 

#[doc="Some documentation comment"] 
pub fn function() {} 

Ed è possibile catturare gli attributi nelle macro. Ci sono già diverse macro che utilizzano questa capacità, il più utilizzato probabilmente essere bitflags!:

macro_rules! bitflags { 
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { 
     $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ 
    }) => 
    ... 
} 

Nota la $(#[$attr:meta])* parte del modello. Cattura tutti gli attributi posizionati prima del rispettivo elemento nel modello. Se scrivi un commento sul documento, verrà effettivamente convertito all'attributo doc e verrà passato a rugdoc, come al solito. Quanto segue è un esempio quick_error cassa che utilizza questo approccio:

quick_error! { 
    #[derive(Debug)] 
    pub enum SomeError { 
     /// IO Error 
     Io(err: io::Error) {} 
     /// Arbitrary system error 
     Sys(errno: nix::Errno) {} 
    } 
} 

e funziona - here è un esempio della struttura generata dal quick_error macro e here è la sua definizione.

+0

Grazie. Questo risolve il mio problema. Sapevo che i doc-comment sono stati tradotti in attributi, ma non mi ero reso conto che potevo associarmi a loro nella definizione della macro. – dnaq