【问题标题】:How to embed a Rust macro variable into documentation?如何将 Rust 宏变量嵌入到文档中?
【发布时间】:2017-04-11 17:56:55
【问题描述】:

我想在宏生成的文档中使用一个宏变量:

macro_rules! impl_foo {
    ($name:ident) => {
        /// Returns a new `$name`.
        fn myfoo() -> $name {

        }
    };
}

但是,变量不会被替换。我也尝试使用#[doc] 属性:

macro_rules! impl_foo {
    ($name:ident) => {
        #[doc = concat!("Returns a new `", $name, "`.")]
        fn myfoo() -> $name {

        }
    };
}

这个竟然解析失败:unexpected token: 'concat'

【问题讨论】:

  • @Shepmaster 我找不到,但我想知道为什么第二个无法解析。
  • 属性内允许的标记集可能非常有限。
  • @torkleyy 宏在解析时没有展开(这就是为什么会有RFC 1628 "Eager expansion of macros"
  • @Shepmaster 我虽然现在程序宏允许属性中的任何标记(但#[doc] 属性本身不知道如何处理这些)。

标签: macros documentation rust


【解决方案1】:

这可以使用递归宏来完成:

macro_rules! impl_foo {
    ($name:ident, $sname:expr) => {
        #[doc = "Returns a new `"]
        #[doc = $sname]
        #[doc = "`."]
        pub fn myfoo() -> $name {
            42
        }
    };

    ($name:tt) => {
        impl_foo!($name, stringify!($name));
    };
}

impl_foo!(u32);


fn main() {
    println!("Hello, world!");
}

呈现为:

【讨论】:

    【解决方案2】:

    虽然the answer @mcarton gave 对于简单的示例确实工作得很好,但对于更复杂的示例它会有点中断。 Rustdoc 似乎在不同的 doc 属性之间插入了空格。降价处理器大部分时间都会将它们剥离,但有时会将它们转换为空格。考虑这个例子:

    macro_rules! impl_foo {
        ($name:ident, $sname:expr) => {
            #[doc = "You can call this as `myfoo("]
            #[doc = $sname]
            #[doc = ")`."]
            pub fn myfoo(_: $name) -> $name {
                42
            }
        };
    
        ($name:tt) => {
            impl_foo!($name, stringify!($name));
        };
    }
    
    impl_foo!(i32);
    
    
    fn main() {
        println!("Hello, world!");
    }
    

    这应该生成文档“您可以将其称为myfoo(i32)。”,但实际上,它会导致“您可以将其称为myfoo( i32 )”。 (注意额外的空格):

    当问题被问到时,我不太确定我的解决方案是否适用于 2017 年的 rustc,但在现代 Rust 中,这可以通过将 stringify!concat! 结合来完成:

    macro_rules! impl_foo {
        ($name:tt) => {
            #[doc = concat!("You can call this as `myfoo(", stringify!($name), ")`.")]
            pub fn myfoo(_: $name) -> $name {
                42
            }
        };
    }
    
    impl_foo!(i32);
    
    
    fn main() {
        println!("Hello, world!");
    }
    

    这会产生您想要的文档(因此,没有多余的空格):

    【讨论】:

      猜你喜欢
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      • 2016-12-31
      • 2015-06-06
      • 1970-01-01
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多