如何在编译器插件中修改 crate 的所有项目?
How to modify all items of a crate in a compiler plugin?
我正在尝试构建一个语法扩展,将属性扩展到调用中。之前:
#[flame]
fn flamed() {
..
}
之后:
fn flamed() {
flame::start_guard("flamed");
..
}
这已经 works。但是,如果我在板条箱级别具有 #[flame]
属性(如 #![flame]
),我也希望它能工作。这可能吗?如果可能,怎么做?
@huon 的评论
Did you try catching ItemKind::Mod in github.com/llogiq/flamer/blob/… and iterating over its contents (recursively)?
很准确——我刚刚添加了一个处理 mod 和特征项的提交。我可能还会添加代码来遍历函数以处理内部项和 fns。
代码如下所示:
fn flame_item(i: &Item) -> Item {
let base = i.clone();
Item {
node: match i.node {
ItemKind::Mod(ref m) =>
ItemKind::Mod(flame_mod(m)),
ItemKind::Trait(unsafety, ref generic, ref bounds, ref tis) =>
ItemKind::Trait(unsafety,
generic.clone(),
bounds.clone(),
flame_items(tis)),
.. // other item types as usual: items, traitimpls, implitems
_ => return base
},
..base
}
}
fn flame_mod(m: &Mod) -> Mod {
Mod {
inner: m.inner,
items: m.items.iter().map(|i| P(flame_item(i))).collect()
}
}
fn flame_items(items: &[TraitItem]) -> Vec<TraitItem> {
items.iter().map(flame_trait_item).collect()
}
我正在尝试构建一个语法扩展,将属性扩展到调用中。之前:
#[flame]
fn flamed() {
..
}
之后:
fn flamed() {
flame::start_guard("flamed");
..
}
这已经 works。但是,如果我在板条箱级别具有 #[flame]
属性(如 #![flame]
),我也希望它能工作。这可能吗?如果可能,怎么做?
@huon 的评论
Did you try catching ItemKind::Mod in github.com/llogiq/flamer/blob/… and iterating over its contents (recursively)?
很准确——我刚刚添加了一个处理 mod 和特征项的提交。我可能还会添加代码来遍历函数以处理内部项和 fns。
代码如下所示:
fn flame_item(i: &Item) -> Item {
let base = i.clone();
Item {
node: match i.node {
ItemKind::Mod(ref m) =>
ItemKind::Mod(flame_mod(m)),
ItemKind::Trait(unsafety, ref generic, ref bounds, ref tis) =>
ItemKind::Trait(unsafety,
generic.clone(),
bounds.clone(),
flame_items(tis)),
.. // other item types as usual: items, traitimpls, implitems
_ => return base
},
..base
}
}
fn flame_mod(m: &Mod) -> Mod {
Mod {
inner: m.inner,
items: m.items.iter().map(|i| P(flame_item(i))).collect()
}
}
fn flame_items(items: &[TraitItem]) -> Vec<TraitItem> {
items.iter().map(flame_trait_item).collect()
}