如何从 crate/模块/函数中派生代码?



据我所知,Rust 支持#[derive]属性在编译时从数据结构生成代码。如何为整个板条箱、模块或函数生成代码?此处不允许使用#[derive]属性。

我想生成一个涉及项目中多个项目(结构/枚举/函数(的函数。

例如,对于此处给定的示例模块

#[derive(MyAgg)]
mod AAA {
struct BBB {}
struct CCC {}
fn ddd() {}
}

我想生产这个。

fn example1() {
print("{:?}", AAA::BBB {});
print("{:?}", AAA::CCC {});
AAA::ddd()
}

这个例子没有意义,但我认为它提供了重点。

#[derive]属性不允许在模块上使用,只允许在结构、枚举和联合上:

error: `derive` may only be applied to structs, enums and unions
--> src/main.rs:1:1
|
1 | #[derive(MyAgg)]
| ^^^^^^^^^^^^^^^^

操场

有关扩展#[derive]宏的更多信息可以在 Rust 书中的 过程宏(和自定义派生(中找到。

但是,您可以创建自己的过程宏。您可以查阅 RFC 以了解过程宏。看看其他板条箱,如Serde或Derivative,也没有什么坏处。

我找到了解决方法。你可以生成一个 Rust 语言解析器并自己解析源代码。

首先,向Cargo.toml添加依赖项。

[dependencies]
syntex_syntax = "0.59.1"

并将这些行添加到src/main.rs.

extern crate syntex_syntax;
use std::path::*;
use syntex_syntax::parse::*;
use syntex_syntax::codemap::*;
fn main() {
let f = file!(); // Get absolute path to this file.
let p = Path::new(f);
let m = FilePathMapping::empty();
let s = ParseSess::new(m);
let r = parse_crate_from_file(&p, &s);
println!("{:?}", r);
}

现在,您有一个解析的 AST。


更新

经过几周的尝试,我了解到宏扩展是在语法解析阶段完成的。由于它在类型分析阶段之前执行,因此我无法查询每种类型的完全解析路径,因此从多个模块稳定引用多个类型变得非常困难或不可能。最后,我放弃了基于宏观的方法。

最新更新