1 个不稳定版本

0.1.0 2022年8月22日

#752 in 过程宏

MIT 许可证

13KB
152

accio

这个crate主要是一个实验,并不适合用于生产环境!

accio 在构建路径中检索分配到多个站点的代码块,并将它们组合到调用位置。

它是在编译时完成的;因此,在加载时间(ctor)或运行时(任何类型的懒初始化)中都不会执行代码。

它允许对函数、枚举、结构体字段、匹配语句等进行部分实现。

它仍然存在许多问题;并且它们在未来可能无法解决。仅举几个例子:

  • 根本不会检查宏执行路径,
  • 明显忽视条件编译标志,
  • 增量编译可能会在宏重新评估时引起一些问题,
  • 错误信息会指向不正确的位置,
  • accio_emit 宏仅按名称匹配;并且不会检查名称冲突,
  • 此crate中的任何宏都不能嵌套,
  • 没有方法使 accio_emit 语句动态引用其自身的路径,
  • 源路径只是简单地递归遍历 .rs 文件;而不是验证这些文件是否被导入到某处,
  • 在解析过程中存在许多可能的错误被静默忽略,
  • 它不适用于文档示例!(是的,文档中的每个示例都是 no_run。)
  • 我根本没有测试它如何与多个crate一起使用。

对于大多数用例;我可以推荐 inventorylinkmector 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