1 个不稳定版本
0.1.0 | 2022年8月22日 |
---|
#752 in 过程宏
13KB
152 行
accio
这个crate主要是一个实验,并不适合用于生产环境!
accio
在构建路径中检索分配到多个站点的代码块,并将它们组合到调用位置。
它是在编译时完成的;因此,在加载时间(ctor
)或运行时(任何类型的懒初始化)中都不会执行代码。
它允许对函数、枚举、结构体字段、匹配语句等进行部分实现。
它仍然存在许多问题;并且它们在未来可能无法解决。仅举几个例子:
- 根本不会检查宏执行路径,
- 明显忽视条件编译标志,
- 增量编译可能会在宏重新评估时引起一些问题,
- 错误信息会指向不正确的位置,
accio_emit
宏仅按名称匹配;并且不会检查名称冲突,- 此crate中的任何宏都不能嵌套,
- 没有方法使
accio_emit
语句动态引用其自身的路径, - 源路径只是简单地递归遍历
.rs
文件;而不是验证这些文件是否被导入到某处, - 在解析过程中存在许多可能的错误被静默忽略,
- 它不适用于文档示例!(是的,文档中的每个示例都是
no_run
。) - 我根本没有测试它如何与多个crate一起使用。
对于大多数用例;我可以推荐 inventory
、linkme
或 ctor
crates。
要自动导入目录中的所有模块,您可以使用 automod
。
贡献
我可能不会回应此crate中的问题;但如果您认为您可以在任何方式使它变得可用;请尝试一下。所以PR是受欢迎的。
用例
accio
可以用于收集函数体中的语句,如下所示
use accio::*;
// some_file.rs
accio_emit! {
// accio_emit's block must be written
// as `scope_name { code_block }` pairs.
// multiple blocks can be listed as follows:
first_scope {
val = 1;
}
second_scope {
val += 2;
}
}
// some_other_file.rs
accio_emit! {
// the same scope name can have multiple
// blocks; these are merged in an
// undetermined order.
second_scope {
val += 3;
}
}
// another_file.rs
let mut val = 0;
assert_eq!(val, 0);
// include the first scope:
// this will evaluate to `val = 1;`
accio!(first_scope);
assert_eq!(val, 1);
// include the second scope:
// this will evaluate to either
// `val += 2; val += 3;` or
// `val += 3; val += 2;`.
accio!(second_scope);
assert_eq!(val, 6);
更有意义的使用案例是自动收集枚举变体。然而,由于Rust的语法规则,accio!
宏不能放置在枚举或结构体的括号内。以下将无法编译
use accio::*;
enum SomeEnum {
accio!(enum_variants)
}
这将产生
error: expected one of `(`, `,`, `=`, `{`, or `}`, found `!`
--> src/lib.rs:60:10
|
5 | accio!(enum_variants)
| ^ expected one of `(`, `,`, `=`, `{`, or `}`
相反,我们可以使用 accio_body
属性宏
use accio::*;
#[accio_body(enum_variants)]
enum SomeEnum {
// this part MUST be empty!
}
#[accio_body(struct_fields)]
struct SomeStruct {
/* this part MUST be empty! */
}
#[accio_body(array_elems)]
static SOME_ARRAY: &[i32] = &[];
accio_emit! {
enum_variants {
FirstVariant,
}
enum_variants {
SecondVariant(String),
}
struct_fields {
pub name: String,
}
array_elems: {
42,
}
}
// ...and so on
请注意,accio_body
实现将代码放入第一个 空 大括号({}
)或方括号([]
)作用域中。因此以下变体将失败
use accio::*;
#[accio_body(enum_variants)]
enum FailingEnum {
// there is code within the braces
AlreadySomeVariant,
}
#[accio_body(struct_fields)]
struct FailingStruct; // no braces!
您仍然可以添加注释,它们不会引起问题。
更多详细示例请参阅 examples/
。
依赖项
~1.5MB
~35K SLoC