api_macros: Improve readability, fix lines >100 chars

This commit is contained in:
Jonas Platte 2020-11-27 22:45:57 +01:00
parent d749f733e2
commit 5175d3d622
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
4 changed files with 112 additions and 85 deletions

View File

@ -39,14 +39,14 @@ pub struct Api {
impl Parse for Api { impl Parse for Api {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> { fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let import_path = util::import_ruma_api(); let ruma_api = util::import_ruma_api();
let metadata: Metadata = input.parse()?; let metadata: Metadata = input.parse()?;
let request: Request = input.parse()?; let request: Request = input.parse()?;
let response: Response = input.parse()?; let response: Response = input.parse()?;
let error_ty = match input.parse::<ErrorType>() { let error_ty = match input.parse::<ErrorType>() {
Ok(err) => err.ty.to_token_stream(), Ok(err) => err.ty.to_token_stream(),
Err(_) => quote! { #import_path::error::Void }, Err(_) => quote! { #ruma_api::error::Void },
}; };
let newtype_body_field = request.newtype_body_field(); let newtype_body_field = request.newtype_body_field();
@ -263,16 +263,22 @@ pub fn expand_all(api: Api) -> syn::Result<TokenStream> {
#[doc = #response_doc] #[doc = #response_doc]
#response_type #response_type
impl ::std::convert::TryFrom<Response> for #ruma_api_import::exports::http::Response<Vec<u8>> { impl ::std::convert::TryFrom<Response>
for #ruma_api_import::exports::http::Response<Vec<u8>>
{
type Error = #ruma_api_import::error::IntoHttpError; type Error = #ruma_api_import::error::IntoHttpError;
#[allow(unused_variables)] #[allow(unused_variables)]
fn try_from(response: Response) -> ::std::result::Result<Self, Self::Error> { fn try_from(response: Response) -> ::std::result::Result<Self, Self::Error> {
let mut resp_builder = #ruma_api_import::exports::http::Response::builder() let mut resp_builder = #ruma_api_import::exports::http::Response::builder()
.header(#ruma_api_import::exports::http::header::CONTENT_TYPE, "application/json"); .header(
#ruma_api_import::exports::http::header::CONTENT_TYPE,
"application/json",
);
let mut headers = let mut headers = resp_builder
resp_builder.headers_mut().expect("`http::ResponseBuilder` is in unusable state"); .headers_mut()
.expect("`http::ResponseBuilder` is in unusable state");
#serialize_response_headers #serialize_response_headers
// This cannot fail because we parse each header value // This cannot fail because we parse each header value
@ -283,7 +289,9 @@ pub fn expand_all(api: Api) -> syn::Result<TokenStream> {
} }
} }
impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Response<Vec<u8>>> for Response { impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Response<Vec<u8>>>
for Response
{
type Error = #ruma_api_import::error::FromHttpResponseError<#error>; type Error = #ruma_api_import::error::FromHttpResponseError<#error>;
#[allow(unused_variables)] #[allow(unused_variables)]

View File

@ -49,41 +49,49 @@ pub struct Request {
impl Request { impl Request {
/// Produces code to add necessary HTTP headers to an `http::Request`. /// Produces code to add necessary HTTP headers to an `http::Request`.
pub fn append_header_kvs(&self) -> TokenStream { pub fn append_header_kvs(&self) -> TokenStream {
let import_path = &self.ruma_api_import; let ruma_api = &self.ruma_api_import;
self.header_fields().map(|request_field| { let http = quote! { #ruma_api::exports::http };
let (field, header_name) = match request_field {
RequestField::Header(field, header_name) => (field, header_name),
_ => unreachable!("expected request field to be header variant"),
};
let field_name = &field.ident; self.header_fields()
.map(|request_field| {
let (field, header_name) = match request_field {
RequestField::Header(field, header_name) => (field, header_name),
_ => unreachable!("expected request field to be header variant"),
};
match &field.ty { let field_name = &field.ident;
syn::Type::Path(syn::TypePath { path: syn::Path { segments, .. }, .. })
if segments.last().unwrap().ident == "Option" => match &field.ty {
{ syn::Type::Path(syn::TypePath { path: syn::Path { segments, .. }, .. })
quote! { if segments.last().unwrap().ident == "Option" =>
if let Some(header_val) = self.#field_name.as_ref() { {
req_builder = req_builder.header( quote! {
#import_path::exports::http::header::#header_name, if let Some(header_val) = self.#field_name.as_ref() {
#import_path::exports::http::header::HeaderValue::from_str(header_val)?, req_builder = req_builder.header(
); #http::header::#header_name,
#http::header::HeaderValue::from_str(header_val)?,
);
}
} }
} }
_ => quote! {
req_builder = req_builder.header(
#http::header::#header_name,
#http::header::HeaderValue::from_str(self.#field_name.as_ref())?,
);
},
} }
_ => quote! { })
req_builder = req_builder.header( .collect()
#import_path::exports::http::header::#header_name,
#import_path::exports::http::header::HeaderValue::from_str(self.#field_name.as_ref())?,
);
},
}
}).collect()
} }
/// Produces code to extract fields from the HTTP headers in an `http::Request`. /// Produces code to extract fields from the HTTP headers in an `http::Request`.
pub fn parse_headers_from_request(&self) -> TokenStream { pub fn parse_headers_from_request(&self) -> TokenStream {
let import_path = &self.ruma_api_import; let ruma_api = &self.ruma_api_import;
let http = quote! { #ruma_api::exports::http };
let serde = quote! { #ruma_api::exports::serde };
let serde_json = quote! { #ruma_api::exports::serde_json };
let fields = self.header_fields().map(|request_field| { let fields = self.header_fields().map(|request_field| {
let (field, header_name) = match request_field { let (field, header_name) = match request_field {
RequestField::Header(field, header_name) => (field, header_name), RequestField::Header(field, header_name) => (field, header_name),
@ -102,11 +110,11 @@ impl Request {
_ => ( _ => (
quote! { header.to_owned() }, quote! { header.to_owned() },
quote! {{ quote! {{
use #import_path::exports::serde::de::Error as _; use #serde::de::Error as _;
// FIXME: Not a missing json field, a missing header! // FIXME: Not a missing json field, a missing header!
return Err(#import_path::error::RequestDeserializationError::new( return Err(#ruma_api::error::RequestDeserializationError::new(
#import_path::exports::serde_json::Error::missing_field( #serde_json::Error::missing_field(
#header_name_string #header_name_string
), ),
request, request,
@ -118,7 +126,7 @@ impl Request {
quote! { quote! {
#field_name: match headers #field_name: match headers
.get(#import_path::exports::http::header::#header_name) .get(#http::header::#header_name)
.and_then(|v| v.to_str().ok()) // FIXME: Should have a distinct error message .and_then(|v| v.to_str().ok()) // FIXME: Should have a distinct error message
{ {
Some(header) => #some_case, Some(header) => #some_case,
@ -433,7 +441,9 @@ impl Parse for Request {
impl ToTokens for Request { impl ToTokens for Request {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let import_path = &self.ruma_api_import; let ruma_api = &self.ruma_api_import;
let ruma_common = quote! { #ruma_api::exports::ruma_common };
let serde = quote! { #ruma_api::exports::serde };
let struct_attributes = &self.attributes; let struct_attributes = &self.attributes;
@ -457,7 +467,7 @@ impl ToTokens for Request {
let (derive_deserialize, lifetimes) = if self.has_body_lifetimes() { let (derive_deserialize, lifetimes) = if self.has_body_lifetimes() {
(TokenStream::new(), self.body_lifetimes()) (TokenStream::new(), self.body_lifetimes())
} else { } else {
(quote!(#import_path::exports::serde::Deserialize), TokenStream::new()) (quote!(#serde::Deserialize), TokenStream::new())
}; };
Some((derive_deserialize, quote! { #lifetimes (#field); })) Some((derive_deserialize, quote! { #lifetimes (#field); }))
@ -466,7 +476,7 @@ impl ToTokens for Request {
let (derive_deserialize, lifetimes) = if self.has_body_lifetimes() { let (derive_deserialize, lifetimes) = if self.has_body_lifetimes() {
(TokenStream::new(), self.body_lifetimes()) (TokenStream::new(), self.body_lifetimes())
} else { } else {
(quote!(#import_path::exports::serde::Deserialize), TokenStream::new()) (quote!(#serde::Deserialize), TokenStream::new())
}; };
let fields = fields.map(RequestField::field); let fields = fields.map(RequestField::field);
@ -479,8 +489,8 @@ impl ToTokens for Request {
/// Data in the request body. /// Data in the request body.
#[derive( #[derive(
Debug, Debug,
#import_path::exports::ruma_common::Outgoing, #ruma_common::Outgoing,
#import_path::exports::serde::Serialize, #serde::Serialize,
#derive_deserialize #derive_deserialize
)] )]
struct RequestBody #def struct RequestBody #def
@ -492,15 +502,15 @@ impl ToTokens for Request {
let (derive_deserialize, lifetime) = if self.has_query_lifetimes() { let (derive_deserialize, lifetime) = if self.has_query_lifetimes() {
(TokenStream::new(), self.query_lifetimes()) (TokenStream::new(), self.query_lifetimes())
} else { } else {
(quote!(#import_path::exports::serde::Deserialize), TokenStream::new()) (quote!(#serde::Deserialize), TokenStream::new())
}; };
quote! { quote! {
/// Data in the request's query string. /// Data in the request's query string.
#[derive( #[derive(
Debug, Debug,
#import_path::exports::ruma_common::Outgoing, #ruma_common::Outgoing,
#import_path::exports::serde::Serialize, #serde::Serialize,
#derive_deserialize #derive_deserialize
)] )]
struct RequestQuery #lifetime (#field); struct RequestQuery #lifetime (#field);
@ -510,15 +520,15 @@ impl ToTokens for Request {
let (derive_deserialize, lifetime) = if self.has_query_lifetimes() { let (derive_deserialize, lifetime) = if self.has_query_lifetimes() {
(TokenStream::new(), self.query_lifetimes()) (TokenStream::new(), self.query_lifetimes())
} else { } else {
(quote!(#import_path::exports::serde::Deserialize), TokenStream::new()) (quote!(#serde::Deserialize), TokenStream::new())
}; };
quote! { quote! {
/// Data in the request's query string. /// Data in the request's query string.
#[derive( #[derive(
Debug, Debug,
#import_path::exports::ruma_common::Outgoing, #ruma_common::Outgoing,
#import_path::exports::serde::Serialize, #serde::Serialize,
#derive_deserialize #derive_deserialize
)] )]
struct RequestQuery #lifetime { struct RequestQuery #lifetime {
@ -530,7 +540,7 @@ impl ToTokens for Request {
}; };
let request = quote! { let request = quote! {
#[derive(Debug, Clone, #import_path::exports::ruma_common::Outgoing)] #[derive(Debug, Clone, #ruma_common::Outgoing)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(!Deserialize)] #[incoming_derive(!Deserialize)]
#( #struct_attributes )* #( #struct_attributes )*

View File

@ -48,7 +48,8 @@ impl Response {
/// Produces code for a response struct initializer. /// Produces code for a response struct initializer.
pub fn init_fields(&self) -> TokenStream { pub fn init_fields(&self) -> TokenStream {
let import_path = &self.ruma_api_import; let ruma_api = &self.ruma_api_import;
let http = quote! { #ruma_api::exports::http };
let mut fields = vec![]; let mut fields = vec![];
let mut new_type_raw_body = None; let mut new_type_raw_body = None;
@ -72,18 +73,18 @@ impl Response {
path: syn::Path { segments, .. }, .. path: syn::Path { segments, .. }, ..
}) if segments.last().unwrap().ident == "Option" => { }) if segments.last().unwrap().ident == "Option" => {
quote! { quote! {
#field_name: #import_path::try_deserialize!( #field_name: #ruma_api::try_deserialize!(
response, response,
headers.remove(#import_path::exports::http::header::#header_name) headers.remove(#http::header::#header_name)
.map(|h| h.to_str().map(|s| s.to_owned())) .map(|h| h.to_str().map(|s| s.to_owned()))
.transpose() .transpose()
) )
} }
} }
_ => quote! { _ => quote! {
#field_name: #import_path::try_deserialize!( #field_name: #ruma_api::try_deserialize!(
response, response,
headers.remove(#import_path::exports::http::header::#header_name) headers.remove(#http::header::#header_name)
.expect("response missing expected header") .expect("response missing expected header")
.to_str() .to_str()
) )
@ -118,7 +119,8 @@ impl Response {
/// Produces code to add necessary HTTP headers to an `http::Response`. /// Produces code to add necessary HTTP headers to an `http::Response`.
pub fn apply_header_fields(&self) -> TokenStream { pub fn apply_header_fields(&self) -> TokenStream {
let import_path = &self.ruma_api_import; let ruma_api = &self.ruma_api_import;
let http = quote! { #ruma_api::exports::http };
let header_calls = self.fields.iter().filter_map(|response_field| { let header_calls = self.fields.iter().filter_map(|response_field| {
if let ResponseField::Header(ref field, ref header_name) = *response_field { if let ResponseField::Header(ref field, ref header_name) = *response_field {
@ -134,7 +136,7 @@ impl Response {
if let Some(header) = response.#field_name { if let Some(header) = response.#field_name {
headers headers
.insert( .insert(
#import_path::exports::http::header::#header_name, #http::header::#header_name,
header.parse()?, header.parse()?,
); );
} }
@ -143,7 +145,7 @@ impl Response {
_ => quote! { _ => quote! {
headers headers
.insert( .insert(
#import_path::exports::http::header::#header_name, #http::header::#header_name,
response.#field_name.parse()?, response.#field_name.parse()?,
); );
}, },
@ -162,7 +164,8 @@ impl Response {
/// Produces code to initialize the struct that will be used to create the response body. /// Produces code to initialize the struct that will be used to create the response body.
pub fn to_body(&self) -> TokenStream { pub fn to_body(&self) -> TokenStream {
let import_path = &self.ruma_api_import; let ruma_api = &self.ruma_api_import;
let serde_json = quote! { #ruma_api::exports::serde_json };
if let Some(field) = self.newtype_raw_body_field() { if let Some(field) = self.newtype_raw_body_field() {
let field_name = field.ident.as_ref().expect("expected field to have an identifier"); let field_name = field.ident.as_ref().expect("expected field to have an identifier");
@ -197,7 +200,7 @@ impl Response {
} }
}; };
quote!(#import_path::exports::serde_json::to_vec(&#body)?) quote!(#serde_json::to_vec(&#body)?)
} }
/// Gets the newtype body field, if this response has one. /// Gets the newtype body field, if this response has one.
@ -308,7 +311,9 @@ impl Parse for Response {
impl ToTokens for Response { impl ToTokens for Response {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let import_path = &self.ruma_api_import; let ruma_api = &self.ruma_api_import;
let ruma_common = quote! { #ruma_api::exports::ruma_common };
let serde = quote! { #ruma_api::exports::serde };
let struct_attributes = &self.attributes; let struct_attributes = &self.attributes;
@ -337,17 +342,12 @@ impl ToTokens for Response {
let response_body_struct = quote! { let response_body_struct = quote! {
/// Data in the response body. /// Data in the response body.
#[derive( #[derive(Debug, #ruma_common::Outgoing, #serde::Deserialize, #serde::Serialize)]
Debug,
#import_path::exports::ruma_common::Outgoing,
#import_path::exports::serde::Deserialize,
#import_path::exports::serde::Serialize,
)]
struct ResponseBody #def struct ResponseBody #def
}; };
let response = quote! { let response = quote! {
#[derive(Debug, Clone, #import_path::exports::ruma_common::Outgoing)] #[derive(Debug, Clone, #ruma_common::Outgoing)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(!Deserialize)] #[incoming_derive(!Deserialize)]
#( #struct_attributes )* #( #struct_attributes )*

View File

@ -151,8 +151,10 @@ pub fn has_lifetime(ty: &Type) -> bool {
pub(crate) fn request_path_string_and_parse( pub(crate) fn request_path_string_and_parse(
request: &Request, request: &Request,
metadata: &Metadata, metadata: &Metadata,
import_path: &TokenStream, ruma_api: &TokenStream,
) -> (TokenStream, TokenStream) { ) -> (TokenStream, TokenStream) {
let percent_encoding = quote! { #ruma_api::exports::percent_encoding };
if request.has_path_fields() { if request.has_path_fields() {
let path_string = metadata.path.value(); let path_string = metadata.path.value();
@ -180,9 +182,9 @@ pub(crate) fn request_path_string_and_parse(
Span::call_site(), Span::call_site(),
); );
format_args.push(quote! { format_args.push(quote! {
#import_path::exports::percent_encoding::utf8_percent_encode( #percent_encoding::utf8_percent_encode(
&self.#path_var.to_string(), &self.#path_var.to_string(),
#import_path::exports::percent_encoding::NON_ALPHANUMERIC, #percent_encoding::NON_ALPHANUMERIC,
) )
}); });
format_string.replace_range(start_of_segment..end_of_segment, "{}"); format_string.replace_range(start_of_segment..end_of_segment, "{}");
@ -200,16 +202,16 @@ pub(crate) fn request_path_string_and_parse(
let path_var_ident = Ident::new(path_var, Span::call_site()); let path_var_ident = Ident::new(path_var, Span::call_site());
quote! { quote! {
#path_var_ident: { #path_var_ident: {
use #import_path::error::RequestDeserializationError; use #ruma_api::error::RequestDeserializationError;
let segment = path_segments.get(#i).unwrap().as_bytes(); let segment = path_segments.get(#i).unwrap().as_bytes();
let decoded = #import_path::try_deserialize!( let decoded = #ruma_api::try_deserialize!(
request, request,
#import_path::exports::percent_encoding::percent_decode(segment) #percent_encoding::percent_decode(segment)
.decode_utf8(), .decode_utf8(),
); );
#import_path::try_deserialize!( #ruma_api::try_deserialize!(
request, request,
::std::convert::TryFrom::try_from(&*decoded), ::std::convert::TryFrom::try_from(&*decoded),
) )
@ -226,7 +228,9 @@ pub(crate) fn request_path_string_and_parse(
/// The function determines the type of query string that needs to be built /// The function determines the type of query string that needs to be built
/// and then builds it using `ruma_serde::urlencoded::to_string`. /// and then builds it using `ruma_serde::urlencoded::to_string`.
pub(crate) fn build_query_string(request: &Request, import_path: &TokenStream) -> TokenStream { pub(crate) fn build_query_string(request: &Request, ruma_api: &TokenStream) -> TokenStream {
let ruma_serde = quote! { #ruma_api::exports::ruma_serde };
if let Some(field) = request.query_map_field() { if let Some(field) = request.query_map_field() {
let field_name = field.ident.as_ref().expect("expected field to have identifier"); let field_name = field.ident.as_ref().expect("expected field to have identifier");
@ -251,7 +255,7 @@ pub(crate) fn build_query_string(request: &Request, import_path: &TokenStream) -
format_args!( format_args!(
"?{}", "?{}",
#import_path::exports::ruma_serde::urlencoded::to_string(request_query)? #ruma_serde::urlencoded::to_string(request_query)?
) )
}) })
} else if request.has_query_fields() { } else if request.has_query_fields() {
@ -264,7 +268,7 @@ pub(crate) fn build_query_string(request: &Request, import_path: &TokenStream) -
format_args!( format_args!(
"?{}", "?{}",
#import_path::exports::ruma_serde::urlencoded::to_string(request_query)? #ruma_serde::urlencoded::to_string(request_query)?
) )
}) })
} else { } else {
@ -273,12 +277,15 @@ pub(crate) fn build_query_string(request: &Request, import_path: &TokenStream) -
} }
/// Deserialize the query string. /// Deserialize the query string.
pub(crate) fn extract_request_query(request: &Request, import_path: &TokenStream) -> TokenStream { pub(crate) fn extract_request_query(request: &Request, ruma_api: &TokenStream) -> TokenStream {
let ruma_common = quote! { #ruma_api::exports::ruma_common };
let ruma_serde = quote! { #ruma_api::exports::ruma_serde };
if request.query_map_field().is_some() { if request.query_map_field().is_some() {
quote! { quote! {
let request_query = #import_path::try_deserialize!( let request_query = #ruma_api::try_deserialize!(
request, request,
#import_path::exports::ruma_serde::urlencoded::from_str( #ruma_serde::urlencoded::from_str(
&request.uri().query().unwrap_or("") &request.uri().query().unwrap_or("")
), ),
); );
@ -287,11 +294,11 @@ pub(crate) fn extract_request_query(request: &Request, import_path: &TokenStream
quote! { quote! {
let request_query: < let request_query: <
RequestQuery RequestQuery
as #import_path::exports::ruma_common::Outgoing as #ruma_common::Outgoing
>::Incoming = >::Incoming =
#import_path::try_deserialize!( #ruma_api::try_deserialize!(
request, request,
#import_path::exports::ruma_serde::urlencoded::from_str( #ruma_serde::urlencoded::from_str(
&request.uri().query().unwrap_or("") &request.uri().query().unwrap_or("")
), ),
); );
@ -304,7 +311,9 @@ pub(crate) fn extract_request_query(request: &Request, import_path: &TokenStream
/// Generates the code to initialize a `Request`. /// Generates the code to initialize a `Request`.
/// ///
/// Used to construct an `http::Request`s body. /// Used to construct an `http::Request`s body.
pub(crate) fn build_request_body(request: &Request, import_path: &TokenStream) -> TokenStream { pub(crate) fn build_request_body(request: &Request, ruma_api: &TokenStream) -> TokenStream {
let serde_json = quote! { #ruma_api::exports::serde_json };
if let Some(field) = request.newtype_raw_body_field() { if let Some(field) = request.newtype_raw_body_field() {
let field_name = field.ident.as_ref().expect("expected field to have an identifier"); let field_name = field.ident.as_ref().expect("expected field to have an identifier");
quote!(self.#field_name) quote!(self.#field_name)
@ -320,7 +329,7 @@ pub(crate) fn build_request_body(request: &Request, import_path: &TokenStream) -
quote! { quote! {
{ {
let request_body = RequestBody #request_body_initializers; let request_body = RequestBody #request_body_initializers;
#import_path::exports::serde_json::to_vec(&request_body)? #serde_json::to_vec(&request_body)?
} }
} }
} else { } else {