♻️ (macros): Deja main/test sin depender de Tokio
Antes delegaban directamente en `#[tokio::main]`/`#[tokio::test]`; ahora construyen su propio runtime vía `pagetop::util::build_runtime()`, con el mismo comportamiento (`Builder::new_multi_thread().enable_all()`). Las extensiones que usan estas macros ya no necesitan declarar Tokio como dependencia directa en su `Cargo.toml`.
This commit is contained in:
parent
24bd13414c
commit
30151b6254
2 changed files with 58 additions and 17 deletions
|
|
@ -39,7 +39,7 @@ mod smart_default;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
use syn::{DeriveInput, parse_macro_input, spanned::Spanned};
|
use syn::{DeriveInput, ItemFn, parse_macro_input, spanned::Spanned};
|
||||||
|
|
||||||
/// Macro para escribir plantillas HTML (basada en [Maud](https://docs.rs/maud)).
|
/// Macro para escribir plantillas HTML (basada en [Maud](https://docs.rs/maud)).
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
|
|
@ -450,19 +450,14 @@ pub fn builder_fn(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let mut output: TokenStream = (quote! {
|
let input = parse_macro_input!(item as ItemFn);
|
||||||
#[::tokio::main]
|
expand_entry(input, false)
|
||||||
})
|
|
||||||
.into();
|
|
||||||
|
|
||||||
output.extend(item);
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define funciones de prueba asíncronas para usar con PageTop.
|
/// Define funciones de prueba asíncronas para usar con PageTop.
|
||||||
///
|
///
|
||||||
/// Usa el *runtime* multi-hilo de **Tokio**, igual que [`#[pagetop::main]`](macro@main), para
|
/// Usa el mismo *runtime* multi-hilo que [`#[pagetop::main]`](macro@main), para garantizar
|
||||||
/// garantizar compatibilidad con extensiones que ejecutan código asíncrono de forma síncrona.
|
/// compatibilidad con extensiones que ejecutan código asíncrono de forma síncrona.
|
||||||
///
|
///
|
||||||
/// # Ejemplo
|
/// # Ejemplo
|
||||||
///
|
///
|
||||||
|
|
@ -474,11 +469,43 @@ pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let mut output: TokenStream = (quote! {
|
let input = parse_macro_input!(item as ItemFn);
|
||||||
#[::tokio::test(flavor = "multi_thread")]
|
expand_entry(input, true)
|
||||||
})
|
}
|
||||||
.into();
|
|
||||||
|
// Genera la función síncrona que envuelve el cuerpo asíncrono original, común a `main` y `test`.
|
||||||
output.extend(item);
|
fn expand_entry(input: ItemFn, is_test: bool) -> TokenStream {
|
||||||
output
|
if input.sig.asyncness.is_none() {
|
||||||
|
return syn::Error::new_spanned(&input.sig.fn_token, "the function must be `async`")
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
let ItemFn {
|
||||||
|
attrs,
|
||||||
|
vis,
|
||||||
|
mut sig,
|
||||||
|
block,
|
||||||
|
} = input;
|
||||||
|
sig.asyncness = None;
|
||||||
|
|
||||||
|
// Ruta absoluta para evitar ambigüedad con `pagetop::test` bajo `use pagetop::prelude::*;`.
|
||||||
|
let test_attr = is_test.then(|| quote! { #[::core::prelude::v1::test] });
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#test_attr
|
||||||
|
#(#attrs)*
|
||||||
|
#vis #sig {
|
||||||
|
#[allow(
|
||||||
|
clippy::expect_used,
|
||||||
|
clippy::diverging_sub_expression,
|
||||||
|
clippy::needless_return,
|
||||||
|
clippy::unwrap_in_result
|
||||||
|
)]
|
||||||
|
{
|
||||||
|
return ::pagetop::util::build_runtime().block_on(async move #block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expanded.into()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
src/util.rs
14
src/util.rs
|
|
@ -25,6 +25,20 @@ pub use pagetop_minimal::paste;
|
||||||
|
|
||||||
// **< FUNCIONES ÚTILES >***************************************************************************
|
// **< FUNCIONES ÚTILES >***************************************************************************
|
||||||
|
|
||||||
|
/// Código requerido por las macros [`pagetop::main`](crate::main) y [`pagetop::test`](crate::test).
|
||||||
|
///
|
||||||
|
/// Equivale a `Builder::new_multi_thread().enable_all().build()`, el mismo runtime que construye
|
||||||
|
/// `#[tokio::main]`/`#[tokio::test(flavor = "multi_thread")]` sin argumentos. Las aplicaciones o
|
||||||
|
/// extensiones que usen estas macros no necesitan declarar `tokio` como dependencia directa en su
|
||||||
|
/// `Cargo.toml`.
|
||||||
|
///
|
||||||
|
/// Esta función no forma parte de la API pública; es `pub` para ser llamada por el código generado
|
||||||
|
/// por las macros.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn build_runtime() -> tokio::runtime::Runtime {
|
||||||
|
tokio::runtime::Runtime::new().expect("Failed to build the Tokio runtime")
|
||||||
|
}
|
||||||
|
|
||||||
/// Errores posibles al normalizar una cadena ASCII con [`normalize_ascii()`].
|
/// Errores posibles al normalizar una cadena ASCII con [`normalize_ascii()`].
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum NormalizeAsciiError {
|
pub enum NormalizeAsciiError {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue