#proc-macro #error #token-stream #error-handling #input #anyhow #emitter

manyhow

proc macro错误处理,类似于anyhow x proc-macro-error

23个不稳定版本 (10个破坏性更新)

0.11.3 2024年7月30日
0.11.1 2024年3月16日
0.10.4 2023年11月24日
0.5.1 2023年7月21日

过程宏 中排名第 49

Download history 10319/week @ 2024-05-04 12515/week @ 2024-05-11 10483/week @ 2024-05-18 12380/week @ 2024-05-25 12548/week @ 2024-06-01 10627/week @ 2024-06-08 11681/week @ 2024-06-15 12200/week @ 2024-06-22 10222/week @ 2024-06-29 13491/week @ 2024-07-06 15374/week @ 2024-07-13 16364/week @ 2024-07-20 16495/week @ 2024-07-27 13746/week @ 2024-08-03 14564/week @ 2024-08-10 14857/week @ 2024-08-17

每月下载量 62,506
218 库中(直接使用14个)

MIT/Apache

77KB
1K SLoC

manyhow

anyhow过程宏版本

CI Status Crates.io Docs.rs Documentation for main

Proc macro anyhow,结合了anyhowproc-macro-error的思路,旨在改善过程宏开发,尤其关注错误处理。

动机

过程宏中的错误处理并不理想,因为过程宏的顶级函数在成功和失败的情况下都只能返回TokenStreams。这意味着我经常编写如下代码,将实际实现移动到单独的函数中,以便能够使用如?之类的 Rust 错误处理。

use proc_macro2::TokenStream as TokenStream2;
                                                                                           
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
    match actual_implementation(input.into()) {
        Ok(output) => output,
        Err(error) => error.into_compile_error(),
    }
    .into()
}
                                                                                           
fn actual_implementation(input: TokenStream2) -> syn::Result<TokenStream2> {
    // ..
}

使用#[manyhow]

要激活错误处理,只需在任一过程宏实现上方添加#[manyhow],将上述示例简化为

use manyhow::manyhow;
use proc_macro2::TokenStream as TokenStream2;
                                                                                           
#[manyhow]
#[proc_macro]
fn my_macro(input: TokenStream2) -> syn::Result<TokenStream2> {
    // ..
}

请参阅不使用宏,以了解其底层展开内容。

被标记为#[manyhow]的过程宏函数可以接受和返回任何TokenStream,也可以返回Result<TokenStream, E>,其中E实现了ToTokensError。作为附加参数,可以指定一个占位符和/或发射器

当用于 proc_macroproc_macro_attribute 时,manyhow 属性可以接受一个可选标志。使用如下格式:#[manyhow(input_as_dummy)] 将会将类似 proc_macro 的函数的输入初始化为 虚拟的 &mut TokenStream,而 #[manyhow(item_as_dummy)]proc_macro_attribute 上会使用注解的项目初始化虚拟对象。

无宏

manyhow 可以在不使用宏的情况下使用,可以通过添加 manyhowdefault-features=false 来禁用。

使用方式基本相同,尽管需要直接调用 functionattributederive 之一,因此有一些额外的样板代码。

虽然示例使用闭包,也可以传递函数。上面的示例将变为

use proc_macro2::TokenStream as TokenStream2;
                                                                                           
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
    manyhow::function(
        input,
        false,
        |input: TokenStream2| -> syn::Result<TokenStream2> {
            // ..
        },
    )
}

Emitter虚拟的 TokenStream 也可以使用。函数和属性接受一个额外的布尔参数,用于控制输入/项目是否用作初始虚拟对象。

emitter: &mutEmitter

MacroHandler(定义 manyhow 可以与哪些闭包/函数一起使用的特质)可以接受对 Emitter 的可变引用。这允许收集错误,但不会立即失败。

Emitter::into_result 可以用来判断 Emitter 是否包含任何值。

use manyhow::{manyhow, Emitter, ErrorMessage};
use proc_macro2::TokenStream as TokenStream2;
                                                                                           
#[manyhow]
#[proc_macro]
fn my_macro(input: TokenStream2, emitter: &mut Emitter) -> manyhow::Result<TokenStream2> {
    // ..
    emitter.emit(ErrorMessage::call_site("A fun error!"));
    emitter.into_result()?;
    // ..
}

dummy: &mutTokenStream

MacroHandler 还接受对 TokenStream 的可变引用,以便在宏出错的情况下发出一些虚拟代码。

这允许通过 ToTokens::to_tokens 添加标记等或直接设置虚拟代码,例如,*dummy = quote!{一些标记}

依赖项

~96–580KB
~13K SLoC