macros: Add response attribute macro

This commit is contained in:
Jonas Platte 2022-10-27 19:31:56 +02:00
parent a83a8e7170
commit f613137b31
No known key found for this signature in database
GPG Key ID: AAA7A61F696C3E0C
4 changed files with 51 additions and 12 deletions

View File

@ -232,6 +232,9 @@ pub use ruma_macros::ruma_api;
/// not just JSON. The field type must be `Vec<u8>`. /// not just JSON. The field type must be `Vec<u8>`.
pub use ruma_macros::request; pub use ruma_macros::request;
// TODO: Write docs
pub use ruma_macros::response;
pub mod error; pub mod error;
mod metadata; mod metadata;

View File

@ -35,16 +35,7 @@ impl Response {
let fields = &self.fields; let fields = &self.fields;
quote! { quote! {
#[doc = #docs] #[doc = #docs]
#[derive( #[#ruma_macros::response(error = #error_ty)]
Clone,
Debug,
#ruma_macros::Response,
#ruma_common::serde::Incoming,
#ruma_common::serde::_FakeDeriveSerde,
)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(!Deserialize, #ruma_macros::_FakeDeriveRumaApi)]
#[ruma_api(error = #error_ty)]
#( #struct_attributes )* #( #struct_attributes )*
pub struct #response_ident { pub struct #response_ident {
#fields #fields

View File

@ -6,7 +6,7 @@ use syn::{
parse::{Parse, ParseStream}, parse::{Parse, ParseStream},
punctuated::Punctuated, punctuated::Punctuated,
visit::Visit, visit::Visit,
DeriveInput, Field, Generics, Ident, Lifetime, Token, Type, DeriveInput, Field, Generics, Ident, ItemStruct, Lifetime, Token, Type,
}; };
use super::attribute::{DeriveResponseMeta, ResponseMeta}; use super::attribute::{DeriveResponseMeta, ResponseMeta};
@ -15,6 +15,42 @@ use crate::util::import_ruma_common;
mod incoming; mod incoming;
mod outgoing; mod outgoing;
pub fn expand_response(attr: ResponseAttr, item: ItemStruct) -> TokenStream {
let ruma_common = import_ruma_common();
let ruma_macros = quote! { #ruma_common::exports::ruma_macros };
let error_ty = attr
.0
.iter()
.find_map(|a| match a {
DeriveResponseMeta::Error(ty) => Some(quote! { #ty }),
_ => None,
})
.unwrap_or_else(|| quote! { #ruma_common::api::error::MatrixError });
quote! {
#[derive(
Clone,
Debug,
#ruma_macros::Response,
#ruma_common::serde::Incoming,
#ruma_common::serde::_FakeDeriveSerde,
)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(!Deserialize, #ruma_macros::_FakeDeriveRumaApi)]
#[ruma_api(error = #error_ty)]
#item
}
}
pub struct ResponseAttr(Punctuated<DeriveResponseMeta, Token![,]>);
impl Parse for ResponseAttr {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
Punctuated::<DeriveResponseMeta, Token![,]>::parse_terminated(input).map(Self)
}
}
pub fn expand_derive_response(input: DeriveInput) -> syn::Result<TokenStream> { pub fn expand_derive_response(input: DeriveInput) -> syn::Result<TokenStream> {
let fields = match input.data { let fields = match input.data {
syn::Data::Struct(s) => s.fields, syn::Data::Struct(s) => s.fields,

View File

@ -27,7 +27,7 @@ mod util;
use self::{ use self::{
api::{ api::{
request::{expand_derive_request, expand_request}, request::{expand_derive_request, expand_request},
response::expand_derive_response, response::{expand_derive_response, expand_response},
Api, Api,
}, },
events::{ events::{
@ -397,6 +397,15 @@ pub fn request(attr: TokenStream, item: TokenStream) -> TokenStream {
expand_request(attr, item).into() expand_request(attr, item).into()
} }
/// > ⚠ If this is the only documentation you see, please navigate to the docs for
/// > `ruma_common::api::response`, where actual documentation can be found.
#[proc_macro_attribute]
pub fn response(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr = parse_macro_input!(attr);
let item = parse_macro_input!(item);
expand_response(attr, item).into()
}
/// Internal helper taking care of the request-specific parts of `ruma_api!`. /// Internal helper taking care of the request-specific parts of `ruma_api!`.
#[proc_macro_derive(Request, attributes(ruma_api))] #[proc_macro_derive(Request, attributes(ruma_api))]
pub fn derive_request(input: TokenStream) -> TokenStream { pub fn derive_request(input: TokenStream) -> TokenStream {