我正在编写一个运行良好的程序宏,但我无法以符合人体工程学的方式报告错误。使用panic!
“有效”但并不优雅,也不能很好地向用户显示错误消息。
我知道我可以在解析 a 时报告好的错误TokenStream
,但是在解析 AST 后我需要在遍历 AST 时产生错误。
宏调用如下所示:
attr_test! {
#[bool]
FOO
}
并且应该输出:
const FOO: bool = false;
这是宏代码:
extern crate proc_macro;
use quote::quote;
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, parse_macro_input, Ident, Meta};
struct AttrTest {
attributes: Vec<Attribute>,
name: Ident,
}
impl Parse for AttrTest {
fn parse(input: ParseStream) -> Result<Self> {
Ok(AttrTest {
attributes: input.call(Attribute::parse_outer)?,
name: input.parse()?,
})
}
}
#[proc_macro]
pub fn attr_test(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
let test: AttrTest = parse_macro_input!(tokens);
let name = test.name;
let first_att = test.attributes
.get(0)
.and_then(|att| att.parse_meta().ok());
if let Some(Meta::Word(ty)) = first_att {
if ty.to_string() != "bool" {
panic!("expected bool");
}
let output = quote! {
const #name: #ty = false;
};
output.into()
} else {
panic!("malformed or missing metadata")
}
}
bool
如果属性中没有指定任何内容,我想产生一个错误。例如,像这样输入:
attr_test! {
#[something_else]
FOO
}
应该导致类似:
error: expected bool
attr_test! {
#[something_else]
^^^^^^^^^^^^^^ expected bool
FOO
}
在解析过程中,有 a Result
,其中包含很多有用的信息,包括 a span
,因此产生的错误可以突出显示有问题的宏调用的确切部分。但是一旦我遍历 AST,我就看不到报告错误的好方法。
这应该怎么做?