作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在使用syn以下示例创建可突变的AST。我了解我可以修改正在移动的节点(如下所示,在当前代码中显示),但是
我很好奇我是否可以在当前节点和下一个节点之间添加一些代码。联合整理箱有能力做到这一点吗?
use syn::visit_mut::{self, VisitMut};
use syn::Expr;
#[derive(Debug)]
struct MyStruct;
impl VisitMut for MyStruct {
fn visit_expr_mut(&mut self, node: &mut Expr) {
if let Expr::MethodCall(expr) = &node.to_owned() {
// I can modify the existing node like so:
*node = parse_quote!("// Hello World");
// How could I add something after this node and before the next?
}
}
}
pub fn create() {
let current_dir = std::env::current_dir().expect("Unable to get current directory");
let rust_file = std::fs::read_to_string(current_dir.join("src").join("lib.rs")).expect("Unable to read rust file");
let ast = syn::parse_file(&rust_file).expect("Unable to create AST from rust file");
MyStruct.visit_file_mut(&mut ast);
}
编辑以显示用例:
#[macro_use]
extern crate foo;
mod test;
fn init(handle: foo::InitHandle) {
handle.add_class::<Test::test>();
}
假设当我阅读AST时,我想为其添加另一个mod和另一个句柄,如下所示:
#[macro_use]
extern crate foo;
mod test;
mod store;
fn init(handle: foo::InitHandle) {
handle.add_class::<Test::test>();
handle.add_class::<Store::store>();
}
最佳答案
正如我所评论的,这在很大程度上取决于您要插入的内容。因为您不能只在node
之前或之后轻松插入任何内容。
对于您的特定情况,可以使用 parse_quote!
生成 ExprBlock
。
*node = parse_quote!(
{
#expr;
handle.add_class::<Store::store>();
}
);
其中具有以下输入:
fn init(handle: foo::InitHandle) {
handle.add_class::<Test::test>();
}
将产生以下输出:
fn init(handle: foo::InitHandle) {
{
handle.add_class::<Test::test>();
handle.add_class::<Store::store>();
};
}
(请注意,我已经重新格式化了输出,以便更漂亮)
visit_block_mut()
。这样,您就可以访问
stmts: Vec<Stmt>
,并且可以在
Stmt
之前和之后插入。
的缺点是,通过这种方式,您将无法像使用
Expr
s那样轻松访问所有
visit_expr_mut()
。
关于rust - 使用VisitMut时如何插入Expr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65765082/
我是一名优秀的程序员,十分优秀!