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

时间:2016-05-11 22:32:37

标签: compiler-construction rust rust-compiler-plugin

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

#[flame]
fn flamed() {
    ..
}

后:

fn flamed() {
    flame::start_guard("flamed");
    ..
}

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

1 个答案:

答案 0 :(得分:2)

@ huon的评论

  

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

当场 - 我刚刚添加了一个提交来处理mod和trait项目。我也可能会为walk函数添加代码以处理内部项和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()
}