我正在使用syn
来解析Rust代码。当我使用field.ty
读取命名字段的类型时,我得到一个syn::Type
。当我使用quote!{#ty}.to_string()
打印它时,我得到"Option<String>"
。
我怎样才能得到qazxsw poi?我想在qazxsw poi中使用qazxsw poi来打印"String"
而不是#ty
。
我想生成如下代码:
quote!
从...开始
"String"
我的尝试:
"Option<String>"
你应该做这样一个未经测试的例子:
impl Foo {
pub set_bar(&mut self, v: String) {
self.bar = Some(v);
}
}
没有太多东西需要解释,它只是“展开”一种类型的不同组件:
struct Foo {
bar: Option<String>
}
- > let ast: DeriveInput = parse_macro_input!(input as DeriveInput);
let data: Data = ast.data;
match data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref fields) => {
fields.named.iter().for_each(|field| {
let name = &field.ident.clone().unwrap();
let ty = &field.ty;
quote!{
impl Foo {
pub set_bar(&mut self, v: #ty) {
self.bar = Some(v);
}
}
};
});
}
_ => {}
},
_ => panic!("You can derive it only from struct"),
}
- > use syn::{GenericArgument, PathArguments, Type};
fn extract_type_from_option(ty: &Type) -> Type {
fn path_is_option(path: &Path) -> bool {
leading_colon.is_none()
&& path.segments.len() == 1
&& path.segments.iter().next().unwrap().ident == "Option"
}
match ty {
Type::Path(typepath) if typepath.qself.is_none() && path_is_option(typepath.path) => {
// Get the first segment of the path (there is only one, in fact: "Option"):
let type_params = typepath.path.segments.iter().first().unwrap().arguments;
// It should have only on angle-bracketed param ("<String>"):
let generic_arg = match type_params {
PathArguments::AngleBracketed(params) => params.args.iter().first().unwrap(),
_ => panic!("TODO: error handling"),
};
// This argument must be a type:
match generic_arg {
GenericArgument::Type(ty) => ty,
_ => panic!("TODO: error handling"),
}
}
_ => panic!("TODO: error handling"),
}
}
- > Type
- > TypePath
- > Path
- > PathSegment
- > PathArguments
。
如果有更简单的方法,我很乐意知道。
请注意,由于AngleBracketedGenericArguments
是一个解析器,它可以使用令牌。你无法确定这是一个GenericArgument
。例如,用户可以输入Type
,或者写syn
。你无法处理这些任意名称。
我的Option
的更新版本,在公共箱子中测试和使用,支持std::option::Option
的几种语法:
type MaybeString = std::option::Option<String>;
Option
Option
std::option::Option
::std::option::Option