我想实现proc_macro_attribute这样一个:
#[component]
struct Div {
#[prop]
color: String,
clicked: bool
}
Run Code Online (Sandbox Code Playgroud)
其中两个属性的 impl 是:
#[proc_macro_attribute]
pub fn component(_attribute: TokenStream, input: TokenStream) -> TokenStream {
modify_struct_and_generate_props_struct(input)
}
// Just as a placeholder attribute for the component attribute to work on.
#[proc_macro_attribute]
pub fn prop(_attribute: TokenStream, input: TokenStream) -> TokenStream {
input
}
Run Code Online (Sandbox Code Playgroud)
我可以使用自定义派生来完成此操作,但这不是我想要在这里实现的目标,因为任何带有注释的结构都#[component]将被修改以包含其他字段。sub#[prop]属性用于创建仅由 prop 字段组成的新结构。
不proc_macro_attribute支持在其上下文中使用的其他子属性,我尝试实现一个单独的属性来缓解这种情况。这会导致编译器出错:
#[component]
struct Div {
#[prop]
color: String,
clicked: bool
}
Run Code Online (Sandbox Code Playgroud)
添加此功能与#![feature(proc_macro)].
我已经在GitHub上定义了问题。你可以查一下它,看看我正在努力实现什么目标。
难道就没有其他可能的出路吗?
如果这不是它本来的样子,我还向 Rust 提出了一个问题。
proc_macro_attribute 不支持其他子属性...
事实上确实如此。
唯一的事情是,编译器不希望最终扩展结构上有任何编译器未知的属性。我正在宏内扩展结构#[component],但保留属性不变#[prop]。这导致编译器搜索该宏的含义并出错。
因此,为了使其发挥作用,请务必在使用该属性后将其从字段中删除。任何残留都会导致编译器出错。
#[proc_macro_attribute]
pub fn component(_attribute: TokenStream, input: TokenStream) -> TokenStream {
let item: syn::Item = syn::parse(input).unwrap();
let props_struct = generate_props_struct(&item);
let modified_struct = modify_struct_and_remove_props_attribute(&item);
quote! {
#props_struct
#modified_struct
}
}
Run Code Online (Sandbox Code Playgroud)
此外,该结构不需要单独定义任何占位符属性。proc_macro_attribute字段上的每个属性都位于结构上放置的上下文中。
我已经用评论更新了github 存储库,以了解如何完成它。