如何在编译器插件中修改包的所有项?

llo*_*giq 5 compiler-construction rust rust-compiler-plugin

我正在尝试构建一个语法扩展,将属性扩展为调用.之前:

#[flame]
fn flamed() {
    ..
}
Run Code Online (Sandbox Code Playgroud)

后:

fn flamed() {
    flame::start_guard("flamed");
    ..
}
Run Code Online (Sandbox Code Playgroud)

这已经有效了.但是,如果我#[flame]在箱子级别(如#![flame])具有属性,我也希望它能够工作.这是可能的,如果是的话,怎么样?

llo*_*giq 2

@huon 的评论

\n\n
\n

您是否尝试在 github.com/llogiq/flamer/blob/\xe2\x80\xa6 中捕获 ItemKind::Mod 并迭代其内容(递归地)?

\n
\n\n

位于 \xe2\x80\x93 上,我刚刚添加了一个提交,通过遍历它们来处理 mod 和 Trait 项目。我还可能添加代码来遍历函数来处理内部项目和 fns。

\n\n

代码如下所示:

\n\n
fn flame_item(i: &Item) -> Item {\n    let base = i.clone();\n    Item {\n        node: match i.node {\n            ItemKind::Mod(ref m) =>\n                ItemKind::Mod(flame_mod(m)),\n            ItemKind::Trait(unsafety, ref generic, ref bounds, ref tis) =>\n                ItemKind::Trait(unsafety,\n                                generic.clone(),\n                                bounds.clone(),\n                                flame_items(tis)),\n        .. // other item types as usual: items, traitimpls, implitems\n\n            _ => return base\n        },\n        ..base\n    }\n}\n\nfn flame_mod(m: &Mod) -> Mod {\n    Mod {\n        inner: m.inner,\n        items: m.items.iter().map(|i| P(flame_item(i))).collect()\n    }\n}\n\nfn flame_items(items: &[TraitItem]) -> Vec<TraitItem> {\n    items.iter().map(flame_trait_item).collect()\n}\n
Run Code Online (Sandbox Code Playgroud)\n