Skip to content

Commit

Permalink
Improve UI when the custom schema fn accepts the wrong argument (#300)
Browse files Browse the repository at this point in the history
  • Loading branch information
msrd0 authored Jan 1, 2023
1 parent 7687e8c commit 67396df
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 32 deletions.
12 changes: 8 additions & 4 deletions derive/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,14 +531,16 @@ fn expand_endpoint_type(
)
});
let output_struct = schema.map(|schema_fn| {
let output_struct_ident = output_struct_ident.as_ref().unwrap_or_else(|| unreachable!());
let output_struct_ident = output_struct_ident
.as_ref()
.unwrap_or_else(|| unreachable!());
let status_codes_fn = status_codes.unwrap_or_else(|| unreachable!());

let schema_call = quote_spanned! { schema_fn.span() =>
let schema: ::gotham_restful::private::OpenapiSchema = #schema_fn(code);
let schema = ::gotham_restful::private::CustomSchema::schema(#schema_fn, code);
};
let status_codes_call = quote_spanned! { status_codes_fn.span() =>
let status_codes: ::std::vec::Vec<::gotham_restful::gotham::hyper::StatusCode> = #status_codes_fn();
let status_codes = ::gotham_restful::private::CustomStatusCodes::status_codes(#status_codes_fn);
};

quote! {
Expand All @@ -563,7 +565,9 @@ fn expand_endpoint_type(
::gotham_restful::IntoResponse::into_response(self.0)
}

fn accepted_types() -> ::core::option::Option<::std::vec::Vec<::gotham_restful::gotham::mime::Mime>> {
fn accepted_types() -> ::core::option::Option<
::std::vec::Vec<::gotham_restful::gotham::mime::Mime>>
{
<#output_ty as ::gotham_restful::IntoResponse>::accepted_types()
}
}
Expand Down
43 changes: 43 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,14 +496,57 @@ pub mod private {
pub use openapi_type::{OpenapiSchema, OpenapiType, Visitor};
pub use serde_json;

#[cfg(feature = "openapi")]
use gotham::hyper::StatusCode;
#[cfg(feature = "auth")]
use gotham::state::{FromState, State};

/// This method is used by the endpoint macro to generate a good error message
/// when the used AuthData type does not implement Clone.
#[cfg(feature = "auth")]
#[inline]
pub fn clone_from_state<T>(state: &State) -> T
where
T: FromState + Clone
{
T::borrow_from(state).clone()
}

/// This trait is used by the endpoint macro to generate a good error message
/// when the schema function has the wrong signature.
#[cfg(feature = "openapi")]
pub trait CustomSchema {
fn schema(self, code: StatusCode) -> OpenapiSchema;
}

#[cfg(feature = "openapi")]
impl<F> CustomSchema for F
where
F: FnOnce(StatusCode) -> OpenapiSchema
{
#[inline]
fn schema(self, code: StatusCode) -> OpenapiSchema {
self(code)
}
}

/// This trait is used by the endpoint macro to generate a good error message
/// when the status_codes function has the wrong signature.
#[cfg(feature = "openapi")]
pub trait CustomStatusCodes {
fn status_codes(self) -> Vec<StatusCode>;
}

#[cfg(feature = "openapi")]
impl<F> CustomStatusCodes for F
where
F: FnOnce() -> Vec<StatusCode>
{
#[inline]
fn status_codes(self) -> Vec<StatusCode> {
self()
}
}
}

#[cfg(feature = "auth")]
Expand Down
39 changes: 11 additions & 28 deletions tests/ui/endpoint/dynamic_schema_wrong_type.stderr
Original file line number Diff line number Diff line change
@@ -1,39 +1,22 @@
error[E0308]: mismatched types
error[E0631]: type mismatch in function arguments
--> tests/ui/endpoint/dynamic_schema_wrong_type.rs:16:21
|
16 | #[read_all(schema = "schema", status_codes = "status_codes")]
| ^^^^^^^^
| |
| expected `u16`, found struct `StatusCode`
| arguments to this function are incorrect
|
note: function defined here
--> tests/ui/endpoint/dynamic_schema_wrong_type.rs:8:4
|
8 | fn schema(_: u16) -> String {
| ^^^^^^ ------
help: call `Into::into` on this expression to convert `StatusCode` into `u16`
|
16 | #[read_all(schema = "schema".into(), status_codes = "status_codes")]
| +++++++

error[E0308]: mismatched types
--> tests/ui/endpoint/dynamic_schema_wrong_type.rs:16:21
|
| --------------------------- found signature defined here
...
16 | #[read_all(schema = "schema", status_codes = "status_codes")]
| ^^^^^^^^
| |
| expected struct `OpenapiSchema`, found struct `std::string::String`
| expected due to this
| ^^^^^^^^ expected due to this
|
= note: expected function signature `fn(StatusCode) -> _`
found function signature `fn(u16) -> _`
= note: required for `fn(u16) -> std::string::String {schema}` to implement `CustomSchema`

error[E0308]: mismatched types
error[E0271]: expected `fn() -> Vec<u16> {status_codes}` to be a fn item that returns `Vec<StatusCode>`, but it returns `Vec<u16>`
--> tests/ui/endpoint/dynamic_schema_wrong_type.rs:16:46
|
16 | #[read_all(schema = "schema", status_codes = "status_codes")]
| ^^^^^^^^^^^^^^
| |
| expected struct `StatusCode`, found `u16`
| expected due to this
| ^^^^^^^^^^^^^^ expected struct `StatusCode`, found `u16`
|
= note: expected struct `Vec<StatusCode>`
found struct `Vec<u16>`
= note: required for `fn() -> Vec<u16> {status_codes}` to implement `CustomStatusCodes`

0 comments on commit 67396df

Please sign in to comment.