aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mingling_macros/src/extensions/routeify.rs11
-rw-r--r--mingling_macros/src/lib.rs22
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