diff options
| -rw-r--r-- | mingling_macros/src/extensions/routeify.rs | 11 | ||||
| -rw-r--r-- | mingling_macros/src/lib.rs | 22 |
2 files changed, 31 insertions, 2 deletions
diff --git a/mingling_macros/src/extensions/routeify.rs b/mingling_macros/src/extensions/routeify.rs index f011fb9..27077ff 100644 --- a/mingling_macros/src/extensions/routeify.rs +++ b/mingling_macros/src/extensions/routeify.rs @@ -10,8 +10,9 @@ use proc_macro::TokenStream; use quote::ToTokens; +use syn::spanned::Spanned; use syn::visit_mut::VisitMut; -use syn::{Expr, ItemFn, parse_macro_input}; +use syn::{parse_macro_input, Expr, ItemFn}; struct RouteifyTransform; @@ -23,8 +24,14 @@ impl VisitMut for RouteifyTransform { let inner = &*try_expr.expr; let inner_tokens = inner.to_token_stream(); + // Set the span of the generated `route` ident to the `?` token's span, + // so that rust-analyzer resolves the `?` position to the `route!` macro + // instead of the standard Try trait, showing the route macro's docs on hover. + let q_span = try_expr.question_token.span(); + let route_ident = proc_macro2::Ident::new("route", q_span); + if let Ok(macro_expr) = syn::parse2::<Expr>(quote::quote! { - ::mingling::macros::route!(#inner_tokens) + ::mingling::macros::#route_ident!(#inner_tokens) }) { *expr = macro_expr; } diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs index a85648f..be355cd 100644 --- a/mingling_macros/src/lib.rs +++ b/mingling_macros/src/lib.rs @@ -511,6 +511,28 @@ pub fn pack_err_structural(input: TokenStream) -> TokenStream { /// directly, while the `Err` value is converted via `Routable::to_chain()` and /// returned early. /// +/// ## Interaction with `#[routeify]` +/// +/// The [`#[routeify]`](attr.routeify.html) attribute macro automatically replaces +/// every `expr?` inside a function with `route!(expr)`. This means you can use the +/// familiar `?` syntax in chain functions instead of writing `route!(...)` +/// explicitly: +/// +/// ```rust,ignore +/// use mingling::macros::chain; +/// +/// #[chain(routeify)] +/// fn process(prev: SomeEntry) -> Next { +/// // `?` here expands to `route!(...)` → this macro → the match block +/// let value = some_fallible_call()?; +/// value.to_chain() +/// } +/// ``` +/// +/// Because `#[routeify]` maps the span of `?` to this macro, hovering over `?` in +/// a `#[routeify]` function will display this documentation — explaining what +/// the `?` actually expands to. +/// /// # Example /// /// ```rust,ignore |
