pavex/blueprint/reflection.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
//! Metadata used by Pavex's CLI to analyze your request
//! handlers, constructors, error handlers, error observers (e.g. their input parameters, their return type,
//! where they are defined, etc.), etc.
//!
//! This module is not meant to be used directly by users of the framework. It is only meant to be
//! used by Pavex's CLI.
#[derive(Debug, Hash, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
/// An implementation detail of the builder.
/// You must use the [`f!`] macro wherever an instance of `RawIdentifiers` is needed.
///
/// [`f!`]: crate::f
pub struct RawIdentifiers {
#[doc(hidden)]
pub import_path: &'static str,
#[doc(hidden)]
pub crate_name: &'static str,
#[doc(hidden)]
pub module_path: &'static str,
#[doc(hidden)]
pub macro_name: &'static str,
}
// The `pavex_ide_hint`-let binding is a hack to "nudge"
// rust-analyzer into parsing the macro input
// as an expression path, therefore enabling auto-completion and
// go-to-definition for the path that's passed as input.
//
// Rust-analyzer doesn't do this by default because it can't infer
// from the macro-generated code what the macro input "looks like".
// `stringify` accepts anything as input, so that's not enough.
//
// The perma-disabled `let` binding lets us workaround the issue
// that an _actual_ `let` binding would cause: it would fail to
// compile if the callable is generic, because the compiler would
// demand to know the type of each generic parameter without a default.
#[macro_export]
/// Convert an [unambiguous callable path](https://pavex.dev/docs/guide/dependency_injection/cookbook/#unambiguous-paths)
/// into [`RawIdentifiers`].
///
/// `f!` is a short-hand for "function-like". It's the macro used to specify a function or a method
/// to be used as a constructor, request handler, etc.
/// Use [`t!`](crate::t), instead, to specify a type when invoking [`Blueprint::prebuilt`].
///
/// # Guide
///
/// In the ["Cookbook"](https://pavex.dev/docs/guide/dependency_injection/cookbook/)
/// section of Pavex's guide on [dependency injection](https://pavex.dev/docs/guide/dependency_injection/)
/// you can find a collection of reference examples on how to use `f!` macro to register different kinds of
/// callables (functions, methods, trait methods, etc.) with a [`Blueprint`].
///
/// [`Blueprint`]: crate::blueprint::Blueprint
/// [`Blueprint::prebuilt`]: crate::blueprint::Blueprint::prebuilt
macro_rules! f {
($p:expr) => {{
#[cfg(pavex_ide_hint)]
let x = $p();
$crate::blueprint::reflection::RawIdentifiers {
import_path: stringify!($p),
crate_name: ::std::env!("CARGO_PKG_NAME", "Failed to load the CARGO_PKG_NAME environment variable. Are you using a custom build system?"),
module_path: module_path!(),
macro_name: "f",
}
}};
}
#[macro_export]
/// Convert an [unambiguous type path](https://pavex.dev/docs/guide/dependency_injection/cookbook/#unambiguous-paths)
/// into [`RawIdentifiers`].
///
/// `t!` is a short-hand for "type". It's the macro used by [`Blueprint::prebuilt`].
/// You should use [`f!`](f) if you're invoking other methods on [`Blueprint`].
///
/// # Guide
///
/// In the ["Cookbook"](https://pavex.dev/docs/guide/dependency_injection/cookbook/)
/// section of Pavex's guide on [dependency injection](https://pavex.dev/docs/guide/dependency_injection/)
/// you can find a collection of reference examples on how to use `t!` macro to register different kinds of
/// types (generic, with lifetimes, etc.) as state inputs with a [`Blueprint`].
///
/// [`Blueprint`]: crate::blueprint::Blueprint
/// [`Blueprint::prebuilt`]: crate::blueprint::Blueprint::prebuilt
macro_rules! t {
// This branch is used by `Blueprint::prebuilt`, where you need to specifically
// pass a type path to the macro.
// The `ty` designator is more restrictive than the `expr` designator, so it's
// the first one we try to match.
($t:ty) => {{
#[cfg(pavex_ide_hint)]
const P: $t;
$crate::blueprint::reflection::RawIdentifiers {
import_path: stringify!($t),
crate_name: ::std::env!("CARGO_PKG_NAME", "Failed to load the CARGO_PKG_NAME environment variable. Are you using a custom build system?"),
module_path: module_path!(),
macro_name: "t",
}
}};
}