我正在创建一个过程宏,它从一些配置文件自动生成一个库(这是一个寄存器布局,但这对这个问题并不重要)。
我想库自动生成的文档伴随着自动库,并包括应与cargo test
运行的文档测试。现在,我已经实现了其中的大部分,但有一个问题我看不到解决方案。
假设我们有一个名为my_lib
的库,我们调用宏来填充它:
use my_macro_lib::hello;
hello!();
它可以扩展为:
/// `foo` will always return `true`
/// ```
/// use my_lib;
/// assert!(my_lib::foo());
/// ```
pub fn foo() -> bool {
true
}
这将按预期运行-cargo doc
将做正确的事情,cargo test
将按预期运行doctests。
问题是在这个例子中,use my_lib
被硬编码到my_macro_lib
中,这显然是不可取的。
我怎样才能创建一个宏来推断正在调用的crate的名称?
我尝试在过程宏中使用macro_rules!
来扩展$crate
,但这违反了卫生规则。
1条答案
按热度按时间watbbzwu1#
您可以通过阅读
CARGO_PKG_NAME
环境变量来获取使用宏的crate的名称。请注意,你必须通过std::env
(在宏的“运行时”)读取它,而 * 不是 * 通过env!
(在编译proc宏crate时)。这里有一些关于在文档注解中插入内容的复杂性。像
/// #an_ident
这样的插值方法不起作用,因为文档注解是以特殊的方式解析的。唯一的方法是创建一个字符串并使用#[doc = ...]
语法。这有点烦人,因为您必须在quote!
调用之前创建字符串,但它可以工作。另一种方法是让用户将crate名称传递给宏:
如果你的宏在每个crate中只被调用一次,这可能是首选的解决方案。如果你的宏被调用了很多次,那么重复crate的名字可能会很烦人。