From f6fc5ed80c1aef13ea04dfb0440a11fffa85457c Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Wed, 26 Jan 2022 23:27:22 +0100 Subject: [PATCH] Move axum-debug into axum-macros (#724) * Move axum-debug into axum-macros * fix ref to axum-macros in changelog * Apply suggestions from code review Co-authored-by: Jonas Platte Co-authored-by: Jonas Platte --- ECOSYSTEM.md | 1 - axum-debug/Cargo.toml | 5 - axum-debug/README.md | 3 + axum-debug/src/lib.rs | 158 +--------- axum-debug/tests/fail/not_a_function.stderr | 5 - axum-macros/Cargo.toml | 1 + axum-macros/LICENSE | 2 +- axum-macros/src/debug_handler.rs | 288 ++++++++++++++++++ axum-macros/src/from_request.rs | 4 +- axum-macros/src/lib.rs | 143 ++++++++- .../tests/debug_handler}/fail/.gitkeep | 0 .../fail/argument_not_extractor.rs | 2 +- .../fail/argument_not_extractor.stderr | 2 +- .../debug_handler}/fail/extract_self_mut.rs | 2 +- .../fail/extract_self_mut.stderr | 2 +- .../debug_handler}/fail/extract_self_ref.rs | 2 +- .../fail/extract_self_ref.stderr | 2 +- .../tests/debug_handler}/fail/generics.rs | 2 +- .../tests/debug_handler}/fail/generics.stderr | 6 +- .../debug_handler}/fail/invalid_attrs.rs | 2 +- .../debug_handler}/fail/invalid_attrs.stderr | 2 +- .../debug_handler}/fail/not_a_function.rs | 2 +- .../debug_handler/fail/not_a_function.stderr | 5 + .../tests/debug_handler}/fail/not_async.rs | 2 +- .../debug_handler}/fail/not_async.stderr | 2 +- .../tests/debug_handler}/fail/not_send.rs | 2 +- .../tests/debug_handler}/fail/not_send.stderr | 6 +- .../fail/too_many_extractors.rs | 2 +- .../fail/too_many_extractors.stderr | 2 +- .../debug_handler}/fail/wrong_return_type.rs | 2 +- .../fail/wrong_return_type.stderr | 8 +- .../pass/associated_fn_without_self.rs | 2 +- .../pass/different_request_body_type.rs | 2 +- .../tests/debug_handler}/pass/impl_future.rs | 2 +- .../debug_handler}/pass/impl_into_response.rs | 2 +- .../pass/multiple_extractors.rs | 2 +- .../debug_handler}/pass/mut_extractor.rs | 2 +- .../tests/debug_handler}/pass/ready.rs | 2 +- .../pass/result_impl_into_response.rs | 2 +- .../tests/debug_handler}/pass/returns_self.rs | 2 +- .../debug_handler}/pass/self_receiver.rs | 2 +- .../fail/double_via_attr.rs | 0 .../fail/double_via_attr.stderr | 4 +- .../tests/{ => from_request}/fail/generic.rs | 0 .../{ => from_request}/fail/generic.stderr | 2 +- .../{ => from_request}/fail/unknown_attr.rs | 0 .../fail/unknown_attr.stderr | 2 +- .../fail/via_on_container_and_field.rs | 0 .../fail/via_on_container_and_field.stderr | 4 +- .../{ => from_request}/pass/container.rs | 0 .../tests/{ => from_request}/pass/named.rs | 0 .../{ => from_request}/pass/named_via.rs | 0 .../tests/{ => from_request}/pass/tuple.rs | 0 .../pass/tuple_same_type_twice.rs | 0 .../pass/tuple_same_type_twice_via.rs | 0 .../{ => from_request}/pass/tuple_via.rs | 0 .../tests/{ => from_request}/pass/unit.rs | 0 axum/src/docs/handlers_intro.md | 2 +- axum/src/handler/mod.rs | 4 +- axum/src/lib.rs | 4 +- 60 files changed, 492 insertions(+), 217 deletions(-) delete mode 100644 axum-debug/tests/fail/not_a_function.stderr create mode 100644 axum-macros/src/debug_handler.rs rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/.gitkeep (100%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/argument_not_extractor.rs (66%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/argument_not_extractor.stderr (79%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/extract_self_mut.rs (92%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/extract_self_mut.stderr (68%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/extract_self_ref.rs (92%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/extract_self_ref.stderr (67%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/generics.rs (64%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/generics.stderr (61%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/invalid_attrs.rs (64%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/invalid_attrs.stderr (60%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/not_a_function.rs (56%) create mode 100644 axum-macros/tests/debug_handler/fail/not_a_function.stderr rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/not_async.rs (60%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/not_async.stderr (58%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/not_send.rs (77%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/not_send.stderr (82%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/too_many_extractors.rs (91%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/too_many_extractors.stderr (83%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/wrong_return_type.rs (69%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/fail/wrong_return_type.stderr (53%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/associated_fn_without_self.rs (72%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/different_request_body_type.rs (89%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/impl_future.rs (78%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/impl_into_response.rs (78%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/multiple_extractors.rs (75%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/mut_extractor.rs (76%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/ready.rs (77%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/result_impl_into_response.rs (98%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/returns_self.rs (88%) rename {axum-debug/tests => axum-macros/tests/debug_handler}/pass/self_receiver.rs (92%) rename axum-macros/tests/{ => from_request}/fail/double_via_attr.rs (100%) rename axum-macros/tests/{ => from_request}/fail/double_via_attr.stderr (77%) rename axum-macros/tests/{ => from_request}/fail/generic.rs (100%) rename axum-macros/tests/{ => from_request}/fail/generic.stderr (72%) rename axum-macros/tests/{ => from_request}/fail/unknown_attr.rs (100%) rename axum-macros/tests/{ => from_request}/fail/unknown_attr.stderr (70%) rename axum-macros/tests/{ => from_request}/fail/via_on_container_and_field.rs (100%) rename axum-macros/tests/{ => from_request}/fail/via_on_container_and_field.stderr (75%) rename axum-macros/tests/{ => from_request}/pass/container.rs (100%) rename axum-macros/tests/{ => from_request}/pass/named.rs (100%) rename axum-macros/tests/{ => from_request}/pass/named_via.rs (100%) rename axum-macros/tests/{ => from_request}/pass/tuple.rs (100%) rename axum-macros/tests/{ => from_request}/pass/tuple_same_type_twice.rs (100%) rename axum-macros/tests/{ => from_request}/pass/tuple_same_type_twice_via.rs (100%) rename axum-macros/tests/{ => from_request}/pass/tuple_via.rs (100%) rename axum-macros/tests/{ => from_request}/pass/unit.rs (100%) diff --git a/ECOSYSTEM.md b/ECOSYSTEM.md index 2fa04bf4..7848eef9 100644 --- a/ECOSYSTEM.md +++ b/ECOSYSTEM.md @@ -8,7 +8,6 @@ If your project isn't listed here and you would like it to be, please feel free - [axum-typed-websockets](https://crates.io/crates/axum-typed-websockets): `axum::extract::ws` with type safe messages. - [tower-cookies](https://crates.io/crates/tower-cookies): Cookie manager middleware - [axum-flash](https://crates.io/crates/axum-flash): One-time notifications (aka flash messages) for axum. -- [axum-debug](https://crates.io/crates/axum-debug): Debugging crate that provides better error messages for axum. - [axum-msgpack](https://crates.io/crates/axum-msgpack): MessagePack Extractors for axum. ## Project showcase diff --git a/axum-debug/Cargo.toml b/axum-debug/Cargo.toml index baa2f1a9..95ef8ac0 100644 --- a/axum-debug/Cargo.toml +++ b/axum-debug/Cargo.toml @@ -17,8 +17,3 @@ proc-macro = true proc-macro2 = "1.0" quote = "1.0" syn = { version = "1.0", features = ["full"] } - -[dev-dependencies] -axum = { path = "../axum", version = "0.4" } -trybuild = "1.0" -rustversion = "1.0" diff --git a/axum-debug/README.md b/axum-debug/README.md index 79686442..e9469ab8 100644 --- a/axum-debug/README.md +++ b/axum-debug/README.md @@ -7,6 +7,8 @@ This is a debugging crate that provides better error messages for [`axum`] framework. +**Note:** this crate is deprecated. Use [axum-macros] instead. + More information about this crate can be found in the [crate documentation][docs]. ## Safety @@ -44,3 +46,4 @@ additional terms or conditions. [docs]: https://docs.rs/axum-debug [license]: /axum-debug/LICENSE [issue]: https://github.com/tokio-rs/axum/issues/new +[axum-macros]: https://crates.io/crates/axum-macros diff --git a/axum-debug/src/lib.rs b/axum-debug/src/lib.rs index 2c3c4116..d4948e8e 100644 --- a/axum-debug/src/lib.rs +++ b/axum-debug/src/lib.rs @@ -1,148 +1,19 @@ //! This is a debugging crate that provides better error messages for [`axum`] framework. //! -//! While using [`axum`], you can get long error messages for simple mistakes. For example: +//! **Note:** this crate is deprecated. Use [axum-macros] instead. //! -//! ```rust,compile_fail -//! use axum::{routing::get, Router}; +//! [axum-macros]: https://crates.io/crates/axum-macros //! -//! #[tokio::main] -//! async fn main() { -//! let app = Router::new().route("/", get(handler)); -//! -//! axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) -//! .serve(app.into_make_service()) -//! .await -//! .unwrap(); -//! } -//! -//! fn handler() -> &'static str { -//! "Hello, world" -//! } -//! ``` -//! -//! You will get a long error message about function not implementing [`Handler`] trait. But why -//! does this function not implement it? To figure it out, the [`debug_handler`] macro can be used. -//! -//! ```rust,compile_fail -//! # use axum::{routing::get, Router}; -//! # use axum_debug::debug_handler; -//! # -//! # #[tokio::main] -//! # async fn main() { -//! # let app = Router::new().route("/", get(handler)); -//! # -//! # axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) -//! # .serve(app.into_make_service()) -//! # .await -//! # .unwrap(); -//! # } -//! # -//! #[debug_handler] -//! fn handler() -> &'static str { -//! "Hello, world" -//! } -//! ``` -//! -//! ```text -//! error: handlers must be async functions -//! --> main.rs:xx:1 -//! | -//! xx | fn handler() -> &'static str { -//! | ^^ -//! ``` -//! -//! As the error message says, handler function needs to be async. -//! -//! ```rust,compile_fail -//! use axum::{routing::get, Router}; -//! use axum_debug::debug_handler; -//! -//! #[tokio::main] -//! async fn main() { -//! let app = Router::new().route("/", get(handler)); -//! -//! axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) -//! .serve(app.into_make_service()) -//! .await -//! .unwrap(); -//! } -//! -//! #[debug_handler] -//! async fn handler() -> &'static str { -//! "Hello, world" -//! } -//! ``` -//! -//! # Changing request body type -//! -//! By default `#[debug_handler]` assumes your request body type is `axum::body::Body`. This will -//! work for most extractors but, for example, it wont work for `Request`, -//! which only implements `FromRequest` and _not_ `FromRequest`. -//! -//! To work around that the request body type can be customized like so: -//! -//! ```rust -//! use axum::{body::BoxBody, http::Request}; -//! # use axum_debug::debug_handler; -//! -//! #[debug_handler(body = BoxBody)] -//! async fn handler(request: Request) {} -//! ``` -//! -//! # Performance -//! -//! Macros in this crate have no effect when using release profile. (eg. `cargo build --release`) -//! -//! [`axum`]: https://docs.rs/axum/0.3 -//! [`Handler`]: https://docs.rs/axum/0.3/axum/handler/trait.Handler.html -//! [`debug_handler`]: macro@debug_handler - -#![warn( - clippy::all, - clippy::dbg_macro, - clippy::todo, - clippy::empty_enum, - clippy::enum_glob_use, - clippy::mem_forget, - clippy::unused_self, - clippy::filter_map_next, - clippy::needless_continue, - clippy::needless_borrow, - clippy::match_wildcard_for_single_variants, - clippy::if_let_mutex, - clippy::mismatched_target_os, - clippy::await_holding_lock, - clippy::match_on_vec_items, - clippy::imprecise_flops, - clippy::suboptimal_flops, - clippy::lossy_float_literal, - clippy::rest_pat_in_fully_bound_structs, - clippy::fn_params_excessive_bools, - clippy::exit, - clippy::inefficient_to_string, - clippy::linkedlist, - clippy::macro_use_imports, - clippy::option_option, - clippy::verbose_file_reads, - clippy::unnested_or_patterns, - clippy::str_to_string, - rust_2018_idioms, - future_incompatible, - nonstandard_style, - missing_debug_implementations, - missing_docs -)] -#![deny(unreachable_pub, private_in_public)] -#![allow(elided_lifetimes_in_paths, clippy::type_complexity)] -#![forbid(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] -#![cfg_attr(test, allow(clippy::float_cmp))] +//! [`axum`]: https://docs.rs/axum/latest use proc_macro::TokenStream; /// Generates better error messages when applied to a handler function. /// -/// See the [module docs](self) for more details. +/// Note this crate is deprecated. Use [axum-macros] instead. +/// +/// [axum-macros]: https://crates.io/crates/axum-macros +#[deprecated(since = "0.3.3", note = "Use the axum-macros crate instead")] #[proc_macro_attribute] pub fn debug_handler(_attr: TokenStream, input: TokenStream) -> TokenStream { #[cfg(not(debug_assertions))] @@ -442,18 +313,3 @@ mod debug_handler { None } } - -#[test] -fn ui() { - #[rustversion::stable] - fn go() { - let t = trybuild::TestCases::new(); - t.compile_fail("tests/fail/*.rs"); - t.pass("tests/pass/*.rs"); - } - - #[rustversion::not(stable)] - fn go() {} - - go(); -} diff --git a/axum-debug/tests/fail/not_a_function.stderr b/axum-debug/tests/fail/not_a_function.stderr deleted file mode 100644 index c15f8796..00000000 --- a/axum-debug/tests/fail/not_a_function.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected `fn` - --> tests/fail/not_a_function.rs:4:1 - | -4 | struct A; - | ^^^^^^ diff --git a/axum-macros/Cargo.toml b/axum-macros/Cargo.toml index 8bb464c5..383fbced 100644 --- a/axum-macros/Cargo.toml +++ b/axum-macros/Cargo.toml @@ -23,4 +23,5 @@ syn = { version = "1.0", features = ["full"] } axum = { path = "../axum", version = "0.4", features = ["headers"] } rustversion = "1.0" serde = { version = "1.0", features = ["derive"] } +tokio = { version = "1.0", features = ["full"] } trybuild = "1.0" diff --git a/axum-macros/LICENSE b/axum-macros/LICENSE index d8b49ec9..538d04ab 100644 --- a/axum-macros/LICENSE +++ b/axum-macros/LICENSE @@ -1,4 +1,4 @@ -Copyright 2021 Axum Debug Contributors +Copyright 2021 Axum Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/axum-macros/src/debug_handler.rs b/axum-macros/src/debug_handler.rs new file mode 100644 index 00000000..e55ed081 --- /dev/null +++ b/axum-macros/src/debug_handler.rs @@ -0,0 +1,288 @@ +use proc_macro2::TokenStream; +use quote::{format_ident, quote, quote_spanned}; +use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, Token, Type}; + +pub(crate) fn expand(attr: Attrs, item_fn: ItemFn) -> syn::Result { + check_extractor_count(&item_fn)?; + + let check_inputs_impls_from_request = check_inputs_impls_from_request(&item_fn, &attr.body_ty); + let check_output_impls_into_response = check_output_impls_into_response(&item_fn); + let check_future_send = check_future_send(&item_fn); + + let tokens = quote! { + #item_fn + #check_inputs_impls_from_request + #check_output_impls_into_response + #check_future_send + }; + + Ok(tokens) +} + +pub(crate) struct Attrs { + body_ty: Type, +} + +impl Parse for Attrs { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let mut body_ty = None; + + while !input.is_empty() { + let ident = input.parse::()?; + if ident == "body" { + input.parse::()?; + body_ty = Some(input.parse()?); + } else { + return Err(syn::Error::new_spanned(ident, "unknown argument")); + } + + let _ = input.parse::(); + } + + let body_ty = body_ty.unwrap_or_else(|| syn::parse_quote!(axum::body::Body)); + + Ok(Self { body_ty }) + } +} + +fn check_extractor_count(item_fn: &ItemFn) -> syn::Result<()> { + let max_extractors = 16; + if item_fn.sig.inputs.len() <= max_extractors { + Ok(()) + } else { + Err(syn::Error::new_spanned( + &item_fn.sig.inputs, + format!( + "Handlers cannot take more than {} arguments. Use `(a, b): (ExtractorA, ExtractorA)` to further nest extractors", + max_extractors, + ) + )) + } +} + +fn check_inputs_impls_from_request(item_fn: &ItemFn, body_ty: &Type) -> TokenStream { + if !item_fn.sig.generics.params.is_empty() { + return syn::Error::new_spanned( + &item_fn.sig.generics, + "`#[axum_macros::debug_handler]` doesn't support generic functions", + ) + .into_compile_error(); + } + + item_fn + .sig + .inputs + .iter() + .enumerate() + .map(|(idx, arg)| { + let (span, ty) = match arg { + FnArg::Receiver(receiver) => { + if receiver.reference.is_some() { + return syn::Error::new_spanned( + receiver, + "Handlers must only take owned values", + ) + .into_compile_error(); + } + + let span = receiver.span(); + (span, syn::parse_quote!(Self)) + } + FnArg::Typed(typed) => { + let ty = &typed.ty; + let span = ty.span(); + (span, ty.clone()) + } + }; + + let name = format_ident!( + "__axum_macros_check_{}_{}_from_request", + item_fn.sig.ident, + idx + ); + quote_spanned! {span=> + #[allow(warnings)] + fn #name() + where + #ty: ::axum::extract::FromRequest<#body_ty> + Send, + {} + } + }) + .collect::() +} + +fn check_output_impls_into_response(item_fn: &ItemFn) -> TokenStream { + let ty = match &item_fn.sig.output { + syn::ReturnType::Default => return quote! {}, + syn::ReturnType::Type(_, ty) => ty, + }; + let span = ty.span(); + + let declare_inputs = item_fn + .sig + .inputs + .iter() + .filter_map(|arg| match arg { + FnArg::Receiver(_) => None, + FnArg::Typed(pat_ty) => { + let pat = &pat_ty.pat; + let ty = &pat_ty.ty; + Some(quote! { + let #pat: #ty = panic!(); + }) + } + }) + .collect::(); + + let block = &item_fn.block; + + let make_value_name = format_ident!( + "__axum_macros_check_{}_into_response_make_value", + item_fn.sig.ident + ); + + let make = if item_fn.sig.asyncness.is_some() { + quote_spanned! {span=> + #[allow(warnings)] + async fn #make_value_name() -> #ty { + #declare_inputs + #block + } + } + } else { + quote_spanned! {span=> + #[allow(warnings)] + fn #make_value_name() -> #ty { + #declare_inputs + #block + } + } + }; + + let name = format_ident!("__axum_macros_check_{}_into_response", item_fn.sig.ident); + + if let Some(receiver) = self_receiver(item_fn) { + quote_spanned! {span=> + #make + + #[allow(warnings)] + async fn #name() { + let value = #receiver #make_value_name().await; + fn check(_: T) + where T: ::axum::response::IntoResponse + {} + check(value); + } + } + } else { + quote_spanned! {span=> + #[allow(warnings)] + async fn #name() { + #make + + let value = #make_value_name().await; + + fn check(_: T) + where T: ::axum::response::IntoResponse + {} + + check(value); + } + } + } +} + +fn check_future_send(item_fn: &ItemFn) -> TokenStream { + if item_fn.sig.asyncness.is_none() { + match &item_fn.sig.output { + syn::ReturnType::Default => { + return syn::Error::new_spanned( + &item_fn.sig.fn_token, + "Handlers must be `async fn`s", + ) + .into_compile_error(); + } + syn::ReturnType::Type(_, ty) => ty, + }; + } + + let span = item_fn.span(); + + let handler_name = &item_fn.sig.ident; + + let args = item_fn.sig.inputs.iter().map(|_| { + quote_spanned! {span=> panic!() } + }); + + let name = format_ident!("__axum_macros_check_{}_future", item_fn.sig.ident); + + if let Some(receiver) = self_receiver(item_fn) { + quote_spanned! {span=> + #[allow(warnings)] + fn #name() { + let future = #receiver #handler_name(#(#args),*); + fn check(_: T) + where T: ::std::future::Future + Send + {} + check(future); + } + } + } else { + quote_spanned! {span=> + #[allow(warnings)] + fn #name() { + #item_fn + + let future = #handler_name(#(#args),*); + fn check(_: T) + where T: ::std::future::Future + Send + {} + check(future); + } + } + } +} + +fn self_receiver(item_fn: &ItemFn) -> Option { + let takes_self = item_fn + .sig + .inputs + .iter() + .any(|arg| matches!(arg, syn::FnArg::Receiver(_))); + if takes_self { + return Some(quote! { Self:: }); + } + + if let syn::ReturnType::Type(_, ty) = &item_fn.sig.output { + if let syn::Type::Path(path) = &**ty { + let segments = &path.path.segments; + if segments.len() == 1 { + if let Some(last) = segments.last() { + match &last.arguments { + syn::PathArguments::None if last.ident == "Self" => { + return Some(quote! { Self:: }); + } + _ => {} + } + } + } + } + } + + None +} + +#[test] +fn ui() { + #[rustversion::stable] + fn go() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/debug_handler/fail/*.rs"); + t.pass("tests/debug_handler/pass/*.rs"); + } + + #[rustversion::not(stable)] + fn go() {} + + go(); +} diff --git a/axum-macros/src/from_request.rs b/axum-macros/src/from_request.rs index 30f3b75b..8e4fa1e8 100644 --- a/axum-macros/src/from_request.rs +++ b/axum-macros/src/from_request.rs @@ -508,8 +508,8 @@ fn ui() { #[rustversion::stable] fn go() { let t = trybuild::TestCases::new(); - t.compile_fail("tests/fail/*.rs"); - t.pass("tests/pass/*.rs"); + t.compile_fail("tests/from_request/fail/*.rs"); + t.pass("tests/from_request/pass/*.rs"); } #[rustversion::not(stable)] diff --git a/axum-macros/src/lib.rs b/axum-macros/src/lib.rs index e7032e86..0b39951e 100644 --- a/axum-macros/src/lib.rs +++ b/axum-macros/src/lib.rs @@ -43,9 +43,11 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(test, allow(clippy::float_cmp))] +use proc_macro::TokenStream; use quote::{quote, ToTokens}; use syn::parse::Parse; +mod debug_handler; mod from_request; /// Derive an implementation of [`FromRequest`]. @@ -235,17 +237,148 @@ mod from_request; /// [`FromRequest`]: https://docs.rs/axum/latest/axum/extract/trait.FromRequest.html /// [`axum::extract::rejection::ExtensionRejection`]: https://docs.rs/axum/latest/axum/extract/rejection/enum.ExtensionRejection.html #[proc_macro_derive(FromRequest, attributes(from_request))] -pub fn derive_from_request(item: proc_macro::TokenStream) -> proc_macro::TokenStream { +pub fn derive_from_request(item: TokenStream) -> TokenStream { expand_with(item, from_request::expand) } -fn expand_with(input: proc_macro::TokenStream, f: F) -> proc_macro::TokenStream +/// Generates better error messages when applied handler functions. +/// +/// While using [`axum`], you can get long error messages for simple mistakes. For example: +/// +/// ```compile_fail +/// use axum::{routing::get, Router}; +/// +/// #[tokio::main] +/// async fn main() { +/// let app = Router::new().route("/", get(handler)); +/// +/// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) +/// .serve(app.into_make_service()) +/// .await +/// .unwrap(); +/// } +/// +/// fn handler() -> &'static str { +/// "Hello, world" +/// } +/// ``` +/// +/// You will get a long error message about function not implementing [`Handler`] trait. But why +/// does this function not implement it? To figure it out, the [`debug_handler`] macro can be used. +/// +/// ```compile_fail +/// # use axum::{routing::get, Router}; +/// # use axum_macros::debug_handler; +/// # +/// # #[tokio::main] +/// # async fn main() { +/// # let app = Router::new().route("/", get(handler)); +/// # +/// # axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) +/// # .serve(app.into_make_service()) +/// # .await +/// # .unwrap(); +/// # } +/// # +/// #[debug_handler] +/// fn handler() -> &'static str { +/// "Hello, world" +/// } +/// ``` +/// +/// ```text +/// error: handlers must be async functions +/// --> main.rs:xx:1 +/// | +/// xx | fn handler() -> &'static str { +/// | ^^ +/// ``` +/// +/// As the error message says, handler function needs to be async. +/// +/// ``` +/// use axum::{routing::get, Router}; +/// use axum_macros::debug_handler; +/// +/// #[tokio::main] +/// async fn main() { +/// # async { +/// let app = Router::new().route("/", get(handler)); +/// +/// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) +/// .serve(app.into_make_service()) +/// .await +/// .unwrap(); +/// # }; +/// } +/// +/// #[debug_handler] +/// async fn handler() -> &'static str { +/// "Hello, world" +/// } +/// ``` +/// +/// # Changing request body type +/// +/// By default `#[debug_handler]` assumes your request body type is `axum::body::Body`. This will +/// work for most extractors but, for example, it wont work for `Request`, +/// which only implements `FromRequest` and _not_ `FromRequest`. +/// +/// To work around that the request body type can be customized like so: +/// +/// ``` +/// use axum::{body::BoxBody, http::Request}; +/// # use axum_macros::debug_handler; +/// +/// #[debug_handler(body = BoxBody)] +/// async fn handler(request: Request) {} +/// ``` +/// +/// # Performance +/// +/// This macro has no effect when compiled with the release profile. (eg. `cargo build --release`) +/// +/// [`axum`]: https://docs.rs/axum/latest +/// [`Handler`]: https://docs.rs/axum/latest/axum/handler/trait.Handler.html +/// [`debug_handler`]: macro@debug_handler +#[proc_macro_attribute] +pub fn debug_handler(_attr: TokenStream, input: TokenStream) -> TokenStream { + #[cfg(not(debug_assertions))] + return input; + + #[cfg(debug_assertions)] + return expand_attr_with(_attr, input, debug_handler::expand); +} + +fn expand_with(input: TokenStream, f: F) -> TokenStream where - F: FnOnce(T) -> syn::Result, - T: Parse, + F: FnOnce(I) -> syn::Result, + I: Parse, K: ToTokens, { - match syn::parse(input).and_then(f) { + expand(syn::parse(input).and_then(f)) +} + +fn expand_attr_with(attr: TokenStream, input: TokenStream, f: F) -> TokenStream +where + F: FnOnce(A, I) -> syn::Result, + A: Parse, + I: Parse, + K: ToTokens, +{ + let expand_result = (|| { + let attr = syn::parse(attr)?; + let input = syn::parse(input)?; + f(attr, input) + })(); + expand(expand_result) +} + +fn expand(result: syn::Result) -> TokenStream +where + T: ToTokens, +{ + match result { Ok(tokens) => { let tokens = (quote! { #tokens }).into(); if std::env::var_os("AXUM_MACROS_DEBUG").is_some() { diff --git a/axum-debug/tests/fail/.gitkeep b/axum-macros/tests/debug_handler/fail/.gitkeep similarity index 100% rename from axum-debug/tests/fail/.gitkeep rename to axum-macros/tests/debug_handler/fail/.gitkeep diff --git a/axum-debug/tests/fail/argument_not_extractor.rs b/axum-macros/tests/debug_handler/fail/argument_not_extractor.rs similarity index 66% rename from axum-debug/tests/fail/argument_not_extractor.rs rename to axum-macros/tests/debug_handler/fail/argument_not_extractor.rs index 0629cde7..afa9a72a 100644 --- a/axum-debug/tests/fail/argument_not_extractor.rs +++ b/axum-macros/tests/debug_handler/fail/argument_not_extractor.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] async fn handler(foo: bool) {} diff --git a/axum-debug/tests/fail/argument_not_extractor.stderr b/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr similarity index 79% rename from axum-debug/tests/fail/argument_not_extractor.stderr rename to axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr index f28dffbc..1694a87e 100644 --- a/axum-debug/tests/fail/argument_not_extractor.stderr +++ b/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `bool: FromRequest` is not satisfied - --> tests/fail/argument_not_extractor.rs:4:23 + --> tests/debug_handler/fail/argument_not_extractor.rs:4:23 | 4 | async fn handler(foo: bool) {} | ^^^^ the trait `FromRequest` is not implemented for `bool` diff --git a/axum-debug/tests/fail/extract_self_mut.rs b/axum-macros/tests/debug_handler/fail/extract_self_mut.rs similarity index 92% rename from axum-debug/tests/fail/extract_self_mut.rs rename to axum-macros/tests/debug_handler/fail/extract_self_mut.rs index 0954136d..01eb636b 100644 --- a/axum-debug/tests/fail/extract_self_mut.rs +++ b/axum-macros/tests/debug_handler/fail/extract_self_mut.rs @@ -2,7 +2,7 @@ use axum::{ async_trait, extract::{FromRequest, RequestParts}, }; -use axum_debug::debug_handler; +use axum_macros::debug_handler; struct A; diff --git a/axum-debug/tests/fail/extract_self_mut.stderr b/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr similarity index 68% rename from axum-debug/tests/fail/extract_self_mut.stderr rename to axum-macros/tests/debug_handler/fail/extract_self_mut.stderr index e0a401e4..595786bf 100644 --- a/axum-debug/tests/fail/extract_self_mut.stderr +++ b/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr @@ -1,5 +1,5 @@ error: Handlers must only take owned values - --> tests/fail/extract_self_mut.rs:23:22 + --> tests/debug_handler/fail/extract_self_mut.rs:23:22 | 23 | async fn handler(&mut self) {} | ^^^^^^^^^ diff --git a/axum-debug/tests/fail/extract_self_ref.rs b/axum-macros/tests/debug_handler/fail/extract_self_ref.rs similarity index 92% rename from axum-debug/tests/fail/extract_self_ref.rs rename to axum-macros/tests/debug_handler/fail/extract_self_ref.rs index f8b3e0ed..d64732cd 100644 --- a/axum-debug/tests/fail/extract_self_ref.rs +++ b/axum-macros/tests/debug_handler/fail/extract_self_ref.rs @@ -2,7 +2,7 @@ use axum::{ async_trait, extract::{FromRequest, RequestParts}, }; -use axum_debug::debug_handler; +use axum_macros::debug_handler; struct A; diff --git a/axum-debug/tests/fail/extract_self_ref.stderr b/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr similarity index 67% rename from axum-debug/tests/fail/extract_self_ref.stderr rename to axum-macros/tests/debug_handler/fail/extract_self_ref.stderr index 8c5e2548..4c0b4950 100644 --- a/axum-debug/tests/fail/extract_self_ref.stderr +++ b/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr @@ -1,5 +1,5 @@ error: Handlers must only take owned values - --> tests/fail/extract_self_ref.rs:23:22 + --> tests/debug_handler/fail/extract_self_ref.rs:23:22 | 23 | async fn handler(&self) {} | ^^^^^ diff --git a/axum-debug/tests/fail/generics.rs b/axum-macros/tests/debug_handler/fail/generics.rs similarity index 64% rename from axum-debug/tests/fail/generics.rs rename to axum-macros/tests/debug_handler/fail/generics.rs index 276fc0df..310de318 100644 --- a/axum-debug/tests/fail/generics.rs +++ b/axum-macros/tests/debug_handler/fail/generics.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] async fn handler() {} diff --git a/axum-debug/tests/fail/generics.stderr b/axum-macros/tests/debug_handler/fail/generics.stderr similarity index 61% rename from axum-debug/tests/fail/generics.stderr rename to axum-macros/tests/debug_handler/fail/generics.stderr index 7249e89d..52b70598 100644 --- a/axum-debug/tests/fail/generics.stderr +++ b/axum-macros/tests/debug_handler/fail/generics.stderr @@ -1,11 +1,11 @@ -error: `#[axum_debug::debug_handler]` doesn't support generic functions - --> tests/fail/generics.rs:4:17 +error: `#[axum_macros::debug_handler]` doesn't support generic functions + --> tests/debug_handler/fail/generics.rs:4:17 | 4 | async fn handler() {} | ^^^ error[E0282]: type annotations needed - --> tests/fail/generics.rs:4:10 + --> tests/debug_handler/fail/generics.rs:4:10 | 4 | async fn handler() {} | ----- ^^^^^^^ cannot infer type for type parameter `T` declared on the function `handler` diff --git a/axum-debug/tests/fail/invalid_attrs.rs b/axum-macros/tests/debug_handler/fail/invalid_attrs.rs similarity index 64% rename from axum-debug/tests/fail/invalid_attrs.rs rename to axum-macros/tests/debug_handler/fail/invalid_attrs.rs index d9fc7f18..1c0ef9b5 100644 --- a/axum-debug/tests/fail/invalid_attrs.rs +++ b/axum-macros/tests/debug_handler/fail/invalid_attrs.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler(foo)] async fn handler() {} diff --git a/axum-debug/tests/fail/invalid_attrs.stderr b/axum-macros/tests/debug_handler/fail/invalid_attrs.stderr similarity index 60% rename from axum-debug/tests/fail/invalid_attrs.stderr rename to axum-macros/tests/debug_handler/fail/invalid_attrs.stderr index 976981c7..20705a0d 100644 --- a/axum-debug/tests/fail/invalid_attrs.stderr +++ b/axum-macros/tests/debug_handler/fail/invalid_attrs.stderr @@ -1,5 +1,5 @@ error: unknown argument - --> tests/fail/invalid_attrs.rs:3:17 + --> tests/debug_handler/fail/invalid_attrs.rs:3:17 | 3 | #[debug_handler(foo)] | ^^^ diff --git a/axum-debug/tests/fail/not_a_function.rs b/axum-macros/tests/debug_handler/fail/not_a_function.rs similarity index 56% rename from axum-debug/tests/fail/not_a_function.rs rename to axum-macros/tests/debug_handler/fail/not_a_function.rs index d3d75162..ced23252 100644 --- a/axum-debug/tests/fail/not_a_function.rs +++ b/axum-macros/tests/debug_handler/fail/not_a_function.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] struct A; diff --git a/axum-macros/tests/debug_handler/fail/not_a_function.stderr b/axum-macros/tests/debug_handler/fail/not_a_function.stderr new file mode 100644 index 00000000..ee561087 --- /dev/null +++ b/axum-macros/tests/debug_handler/fail/not_a_function.stderr @@ -0,0 +1,5 @@ +error: expected `fn` + --> tests/debug_handler/fail/not_a_function.rs:4:1 + | +4 | struct A; + | ^^^^^^ diff --git a/axum-debug/tests/fail/not_async.rs b/axum-macros/tests/debug_handler/fail/not_async.rs similarity index 60% rename from axum-debug/tests/fail/not_async.rs rename to axum-macros/tests/debug_handler/fail/not_async.rs index eced8ec0..fbda0151 100644 --- a/axum-debug/tests/fail/not_async.rs +++ b/axum-macros/tests/debug_handler/fail/not_async.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] fn handler() {} diff --git a/axum-debug/tests/fail/not_async.stderr b/axum-macros/tests/debug_handler/fail/not_async.stderr similarity index 58% rename from axum-debug/tests/fail/not_async.stderr rename to axum-macros/tests/debug_handler/fail/not_async.stderr index e196a06b..ccdc5bc2 100644 --- a/axum-debug/tests/fail/not_async.stderr +++ b/axum-macros/tests/debug_handler/fail/not_async.stderr @@ -1,5 +1,5 @@ error: Handlers must be `async fn`s - --> tests/fail/not_async.rs:4:1 + --> tests/debug_handler/fail/not_async.rs:4:1 | 4 | fn handler() {} | ^^ diff --git a/axum-debug/tests/fail/not_send.rs b/axum-macros/tests/debug_handler/fail/not_send.rs similarity index 77% rename from axum-debug/tests/fail/not_send.rs rename to axum-macros/tests/debug_handler/fail/not_send.rs index 4013db61..df43c9b9 100644 --- a/axum-debug/tests/fail/not_send.rs +++ b/axum-macros/tests/debug_handler/fail/not_send.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] async fn handler() { diff --git a/axum-debug/tests/fail/not_send.stderr b/axum-macros/tests/debug_handler/fail/not_send.stderr similarity index 82% rename from axum-debug/tests/fail/not_send.stderr rename to axum-macros/tests/debug_handler/fail/not_send.stderr index 5d8bc96e..9c6528a8 100644 --- a/axum-debug/tests/fail/not_send.stderr +++ b/axum-macros/tests/debug_handler/fail/not_send.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> tests/fail/not_send.rs:4:1 + --> tests/debug_handler/fail/not_send.rs:4:1 | 4 | async fn handler() { | ^^^^^ future returned by `handler` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> tests/fail/not_send.rs:6:5 + --> tests/debug_handler/fail/not_send.rs:6:5 | 5 | let rc = std::rc::Rc::new(()); | -- has type `Rc<()>` which is not `Send` @@ -15,7 +15,7 @@ note: future is not `Send` as this value is used across an await 7 | } | - `rc` is later dropped here note: required by a bound in `check` - --> tests/fail/not_send.rs:4:1 + --> tests/debug_handler/fail/not_send.rs:4:1 | 4 | async fn handler() { | ^^^^^ required by this bound in `check` diff --git a/axum-debug/tests/fail/too_many_extractors.rs b/axum-macros/tests/debug_handler/fail/too_many_extractors.rs similarity index 91% rename from axum-debug/tests/fail/too_many_extractors.rs rename to axum-macros/tests/debug_handler/fail/too_many_extractors.rs index 9e151faa..d24fdcbb 100644 --- a/axum-debug/tests/fail/too_many_extractors.rs +++ b/axum-macros/tests/debug_handler/fail/too_many_extractors.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] async fn handler( diff --git a/axum-debug/tests/fail/too_many_extractors.stderr b/axum-macros/tests/debug_handler/fail/too_many_extractors.stderr similarity index 83% rename from axum-debug/tests/fail/too_many_extractors.stderr rename to axum-macros/tests/debug_handler/fail/too_many_extractors.stderr index f4458c48..a1afce89 100644 --- a/axum-debug/tests/fail/too_many_extractors.stderr +++ b/axum-macros/tests/debug_handler/fail/too_many_extractors.stderr @@ -1,5 +1,5 @@ error: Handlers cannot take more than 16 arguments. Use `(a, b): (ExtractorA, ExtractorA)` to further nest extractors - --> tests/fail/too_many_extractors.rs:5:5 + --> tests/debug_handler/fail/too_many_extractors.rs:5:5 | 5 | / e1: String, 6 | | e2: String, diff --git a/axum-debug/tests/fail/wrong_return_type.rs b/axum-macros/tests/debug_handler/fail/wrong_return_type.rs similarity index 69% rename from axum-debug/tests/fail/wrong_return_type.rs rename to axum-macros/tests/debug_handler/fail/wrong_return_type.rs index 4ddf636d..f7afbe0f 100644 --- a/axum-debug/tests/fail/wrong_return_type.rs +++ b/axum-macros/tests/debug_handler/fail/wrong_return_type.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] async fn handler() -> bool { diff --git a/axum-debug/tests/fail/wrong_return_type.stderr b/axum-macros/tests/debug_handler/fail/wrong_return_type.stderr similarity index 53% rename from axum-debug/tests/fail/wrong_return_type.stderr rename to axum-macros/tests/debug_handler/fail/wrong_return_type.stderr index 596ba1d7..37fba61f 100644 --- a/axum-debug/tests/fail/wrong_return_type.stderr +++ b/axum-macros/tests/debug_handler/fail/wrong_return_type.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `bool: IntoResponse` is not satisfied - --> tests/fail/wrong_return_type.rs:4:23 + --> tests/debug_handler/fail/wrong_return_type.rs:4:23 | 4 | async fn handler() -> bool { | ^^^^ the trait `IntoResponse` is not implemented for `bool` | -note: required by a bound in `__axum_debug_check_handler_into_response::{closure#0}::check` - --> tests/fail/wrong_return_type.rs:4:23 +note: required by a bound in `__axum_macros_check_handler_into_response::{closure#0}::check` + --> tests/debug_handler/fail/wrong_return_type.rs:4:23 | 4 | async fn handler() -> bool { - | ^^^^ required by this bound in `__axum_debug_check_handler_into_response::{closure#0}::check` + | ^^^^ required by this bound in `__axum_macros_check_handler_into_response::{closure#0}::check` diff --git a/axum-debug/tests/pass/associated_fn_without_self.rs b/axum-macros/tests/debug_handler/pass/associated_fn_without_self.rs similarity index 72% rename from axum-debug/tests/pass/associated_fn_without_self.rs rename to axum-macros/tests/debug_handler/pass/associated_fn_without_self.rs index 009ac3a8..157b5593 100644 --- a/axum-debug/tests/pass/associated_fn_without_self.rs +++ b/axum-macros/tests/debug_handler/pass/associated_fn_without_self.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; struct A; diff --git a/axum-debug/tests/pass/different_request_body_type.rs b/axum-macros/tests/debug_handler/pass/different_request_body_type.rs similarity index 89% rename from axum-debug/tests/pass/different_request_body_type.rs rename to axum-macros/tests/debug_handler/pass/different_request_body_type.rs index 0a2467d8..715e5aec 100644 --- a/axum-debug/tests/pass/different_request_body_type.rs +++ b/axum-macros/tests/debug_handler/pass/different_request_body_type.rs @@ -1,5 +1,5 @@ use axum::{body::BoxBody, http::Request}; -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler(body = BoxBody)] async fn handler(_: Request) {} diff --git a/axum-debug/tests/pass/impl_future.rs b/axum-macros/tests/debug_handler/pass/impl_future.rs similarity index 78% rename from axum-debug/tests/pass/impl_future.rs rename to axum-macros/tests/debug_handler/pass/impl_future.rs index 9259f62a..7037f5e1 100644 --- a/axum-debug/tests/pass/impl_future.rs +++ b/axum-macros/tests/debug_handler/pass/impl_future.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; use std::future::Future; #[debug_handler] diff --git a/axum-debug/tests/pass/impl_into_response.rs b/axum-macros/tests/debug_handler/pass/impl_into_response.rs similarity index 78% rename from axum-debug/tests/pass/impl_into_response.rs rename to axum-macros/tests/debug_handler/pass/impl_into_response.rs index db17a12b..69b884e3 100644 --- a/axum-debug/tests/pass/impl_into_response.rs +++ b/axum-macros/tests/debug_handler/pass/impl_into_response.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; use axum::response::IntoResponse; #[debug_handler] diff --git a/axum-debug/tests/pass/multiple_extractors.rs b/axum-macros/tests/debug_handler/pass/multiple_extractors.rs similarity index 75% rename from axum-debug/tests/pass/multiple_extractors.rs rename to axum-macros/tests/debug_handler/pass/multiple_extractors.rs index d5de6a4e..5c7ab044 100644 --- a/axum-debug/tests/pass/multiple_extractors.rs +++ b/axum-macros/tests/debug_handler/pass/multiple_extractors.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] async fn handler(_one: String, _two: String, _three: String) {} diff --git a/axum-debug/tests/pass/mut_extractor.rs b/axum-macros/tests/debug_handler/pass/mut_extractor.rs similarity index 76% rename from axum-debug/tests/pass/mut_extractor.rs rename to axum-macros/tests/debug_handler/pass/mut_extractor.rs index 872e10c5..2f9c9d71 100644 --- a/axum-debug/tests/pass/mut_extractor.rs +++ b/axum-macros/tests/debug_handler/pass/mut_extractor.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; #[debug_handler] async fn handler(mut foo: String) -> String { diff --git a/axum-debug/tests/pass/ready.rs b/axum-macros/tests/debug_handler/pass/ready.rs similarity index 77% rename from axum-debug/tests/pass/ready.rs rename to axum-macros/tests/debug_handler/pass/ready.rs index a5bc533a..4ee73e99 100644 --- a/axum-debug/tests/pass/ready.rs +++ b/axum-macros/tests/debug_handler/pass/ready.rs @@ -1,4 +1,4 @@ -use axum_debug::debug_handler; +use axum_macros::debug_handler; use std::future::{Ready, ready}; #[debug_handler] diff --git a/axum-debug/tests/pass/result_impl_into_response.rs b/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs similarity index 98% rename from axum-debug/tests/pass/result_impl_into_response.rs rename to axum-macros/tests/debug_handler/pass/result_impl_into_response.rs index c35773c7..81269a9c 100644 --- a/axum-debug/tests/pass/result_impl_into_response.rs +++ b/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs @@ -3,7 +3,7 @@ use axum::{ extract::{FromRequest, RequestParts}, response::IntoResponse, }; -use axum_debug::debug_handler; +use axum_macros::debug_handler; fn main() {} diff --git a/axum-debug/tests/pass/returns_self.rs b/axum-macros/tests/debug_handler/pass/returns_self.rs similarity index 88% rename from axum-debug/tests/pass/returns_self.rs rename to axum-macros/tests/debug_handler/pass/returns_self.rs index 9c9c09a2..a8bb47e6 100644 --- a/axum-debug/tests/pass/returns_self.rs +++ b/axum-macros/tests/debug_handler/pass/returns_self.rs @@ -1,5 +1,5 @@ use axum::response::{IntoResponse, Response}; -use axum_debug::debug_handler; +use axum_macros::debug_handler; struct A; diff --git a/axum-debug/tests/pass/self_receiver.rs b/axum-macros/tests/debug_handler/pass/self_receiver.rs similarity index 92% rename from axum-debug/tests/pass/self_receiver.rs rename to axum-macros/tests/debug_handler/pass/self_receiver.rs index c9d23d25..f22ccc08 100644 --- a/axum-debug/tests/pass/self_receiver.rs +++ b/axum-macros/tests/debug_handler/pass/self_receiver.rs @@ -2,7 +2,7 @@ use axum::{ async_trait, extract::{FromRequest, RequestParts}, }; -use axum_debug::debug_handler; +use axum_macros::debug_handler; struct A; diff --git a/axum-macros/tests/fail/double_via_attr.rs b/axum-macros/tests/from_request/fail/double_via_attr.rs similarity index 100% rename from axum-macros/tests/fail/double_via_attr.rs rename to axum-macros/tests/from_request/fail/double_via_attr.rs diff --git a/axum-macros/tests/fail/double_via_attr.stderr b/axum-macros/tests/from_request/fail/double_via_attr.stderr similarity index 77% rename from axum-macros/tests/fail/double_via_attr.stderr rename to axum-macros/tests/from_request/fail/double_via_attr.stderr index 9aa3f611..e63d4502 100644 --- a/axum-macros/tests/fail/double_via_attr.stderr +++ b/axum-macros/tests/from_request/fail/double_via_attr.stderr @@ -1,11 +1,11 @@ error: `via` specified more than once - --> tests/fail/double_via_attr.rs:5:49 + --> tests/from_request/fail/double_via_attr.rs:5:49 | 5 | struct Extractor(#[from_request(via(Extension), via(Extension))] State); | ^^^ warning: unused import: `axum::extract::Extension` - --> tests/fail/double_via_attr.rs:2:5 + --> tests/from_request/fail/double_via_attr.rs:2:5 | 2 | use axum::extract::Extension; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/axum-macros/tests/fail/generic.rs b/axum-macros/tests/from_request/fail/generic.rs similarity index 100% rename from axum-macros/tests/fail/generic.rs rename to axum-macros/tests/from_request/fail/generic.rs diff --git a/axum-macros/tests/fail/generic.stderr b/axum-macros/tests/from_request/fail/generic.stderr similarity index 72% rename from axum-macros/tests/fail/generic.stderr rename to axum-macros/tests/from_request/fail/generic.stderr index b9f5572f..51ca3ae3 100644 --- a/axum-macros/tests/fail/generic.stderr +++ b/axum-macros/tests/from_request/fail/generic.stderr @@ -1,5 +1,5 @@ error: `#[derive(FromRequest)] doesn't support generics - --> tests/fail/generic.rs:4:17 + --> tests/from_request/fail/generic.rs:4:17 | 4 | struct Extractor(Option); | ^^^ diff --git a/axum-macros/tests/fail/unknown_attr.rs b/axum-macros/tests/from_request/fail/unknown_attr.rs similarity index 100% rename from axum-macros/tests/fail/unknown_attr.rs rename to axum-macros/tests/from_request/fail/unknown_attr.rs diff --git a/axum-macros/tests/fail/unknown_attr.stderr b/axum-macros/tests/from_request/fail/unknown_attr.stderr similarity index 70% rename from axum-macros/tests/fail/unknown_attr.stderr rename to axum-macros/tests/from_request/fail/unknown_attr.stderr index 224b1312..b6422fed 100644 --- a/axum-macros/tests/fail/unknown_attr.stderr +++ b/axum-macros/tests/from_request/fail/unknown_attr.stderr @@ -1,5 +1,5 @@ error: expected `via` - --> tests/fail/unknown_attr.rs:4:33 + --> tests/from_request/fail/unknown_attr.rs:4:33 | 4 | struct Extractor(#[from_request(foo)] String); | ^^^ diff --git a/axum-macros/tests/fail/via_on_container_and_field.rs b/axum-macros/tests/from_request/fail/via_on_container_and_field.rs similarity index 100% rename from axum-macros/tests/fail/via_on_container_and_field.rs rename to axum-macros/tests/from_request/fail/via_on_container_and_field.rs diff --git a/axum-macros/tests/fail/via_on_container_and_field.stderr b/axum-macros/tests/from_request/fail/via_on_container_and_field.stderr similarity index 75% rename from axum-macros/tests/fail/via_on_container_and_field.stderr rename to axum-macros/tests/from_request/fail/via_on_container_and_field.stderr index 8700d19b..01b6cac0 100644 --- a/axum-macros/tests/fail/via_on_container_and_field.stderr +++ b/axum-macros/tests/from_request/fail/via_on_container_and_field.stderr @@ -1,11 +1,11 @@ error: `#[from_request(via(...))]` on a field cannot be used together with `#[from_request(...)]` on the container - --> tests/fail/via_on_container_and_field.rs:6:33 + --> tests/from_request/fail/via_on_container_and_field.rs:6:33 | 6 | struct Extractor(#[from_request(via(Extension))] State); | ^^^ warning: unused import: `axum::extract::Extension` - --> tests/fail/via_on_container_and_field.rs:2:5 + --> tests/from_request/fail/via_on_container_and_field.rs:2:5 | 2 | use axum::extract::Extension; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/axum-macros/tests/pass/container.rs b/axum-macros/tests/from_request/pass/container.rs similarity index 100% rename from axum-macros/tests/pass/container.rs rename to axum-macros/tests/from_request/pass/container.rs diff --git a/axum-macros/tests/pass/named.rs b/axum-macros/tests/from_request/pass/named.rs similarity index 100% rename from axum-macros/tests/pass/named.rs rename to axum-macros/tests/from_request/pass/named.rs diff --git a/axum-macros/tests/pass/named_via.rs b/axum-macros/tests/from_request/pass/named_via.rs similarity index 100% rename from axum-macros/tests/pass/named_via.rs rename to axum-macros/tests/from_request/pass/named_via.rs diff --git a/axum-macros/tests/pass/tuple.rs b/axum-macros/tests/from_request/pass/tuple.rs similarity index 100% rename from axum-macros/tests/pass/tuple.rs rename to axum-macros/tests/from_request/pass/tuple.rs diff --git a/axum-macros/tests/pass/tuple_same_type_twice.rs b/axum-macros/tests/from_request/pass/tuple_same_type_twice.rs similarity index 100% rename from axum-macros/tests/pass/tuple_same_type_twice.rs rename to axum-macros/tests/from_request/pass/tuple_same_type_twice.rs diff --git a/axum-macros/tests/pass/tuple_same_type_twice_via.rs b/axum-macros/tests/from_request/pass/tuple_same_type_twice_via.rs similarity index 100% rename from axum-macros/tests/pass/tuple_same_type_twice_via.rs rename to axum-macros/tests/from_request/pass/tuple_same_type_twice_via.rs diff --git a/axum-macros/tests/pass/tuple_via.rs b/axum-macros/tests/from_request/pass/tuple_via.rs similarity index 100% rename from axum-macros/tests/pass/tuple_via.rs rename to axum-macros/tests/from_request/pass/tuple_via.rs diff --git a/axum-macros/tests/pass/unit.rs b/axum-macros/tests/from_request/pass/unit.rs similarity index 100% rename from axum-macros/tests/pass/unit.rs rename to axum-macros/tests/from_request/pass/unit.rs diff --git a/axum/src/docs/handlers_intro.md b/axum/src/docs/handlers_intro.md index 4da89baf..7697e127 100644 --- a/axum/src/docs/handlers_intro.md +++ b/axum/src/docs/handlers_intro.md @@ -5,4 +5,4 @@ can be converted [into a response](crate::response). Handlers is where your application logic lives and axum applications are built by routing between handlers. -[`debug_handler`]: https://docs.rs/axum-debug/latest/axum_debug/attr.debug_handler.html +[`debug_handler`]: https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html diff --git a/axum/src/handler/mod.rs b/axum/src/handler/mod.rs index 57a09444..f30fb775 100644 --- a/axum/src/handler/mod.rs +++ b/axum/src/handler/mod.rs @@ -66,9 +66,9 @@ //! //! This error doesn't tell you _why_ your function doesn't implement //! [`Handler`]. It's possible to improve the error with the [`debug_handler`] -//! proc-macro from the [axum-debug] crate. +//! proc-macro from the [axum-macros] crate. //! -//! [axum-debug]: https://docs.rs/axum-debug +//! [axum-macros]: https://docs.rs/axum-macros use crate::{ body::{boxed, Body, Bytes, HttpBody}, diff --git a/axum/src/lib.rs b/axum/src/lib.rs index 238dd22a..64d0144a 100644 --- a/axum/src/lib.rs +++ b/axum/src/lib.rs @@ -406,8 +406,8 @@ //! [`HeaderMap`]: http::header::HeaderMap //! [`Request`]: http::Request //! [customize-extractor-error]: https://github.com/tokio-rs/axum/blob/main/examples/customize-extractor-error/src/main.rs -//! [axum-debug]: https://docs.rs/axum-debug -//! [`debug_handler`]: https://docs.rs/axum-debug/latest/axum_debug/attr.debug_handler.html +//! [axum-macros]: https://docs.rs/axum-macros +//! [`debug_handler`]: https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html //! [`Handler`]: crate::handler::Handler //! [`Infallible`]: std::convert::Infallible //! [load shed]: tower::load_shed