Split enum and struct derives

This commit is contained in:
Joel Wachsler 2022-07-24 02:14:40 +00:00
parent 3ca87f0fc1
commit e17deeb354
4 changed files with 54 additions and 24 deletions

View File

@ -6,16 +6,22 @@ use quote::quote;
use super::{group_method::GroupMethod, skeleton::auth_ident, util}; use super::{group_method::GroupMethod, skeleton::auth_ident, util};
#[derive(Debug)] #[derive(Debug)]
pub struct GroupGeneration { pub struct GroupGeneration<'a> {
api_group: parser::ApiGroup, api_group: parser::ApiGroup,
response_derives: Vec<String>, struct_derives: &'a [&'a str],
enum_derives: &'a [&'a str],
} }
impl GroupGeneration { impl<'a> GroupGeneration<'a> {
pub fn new(api_group: parser::ApiGroup, response_derives: Vec<String>) -> Self { pub fn new(
api_group: parser::ApiGroup,
struct_derives: &'a [&'a str],
enum_derives: &'a [&'a str],
) -> Self {
Self { Self {
api_group, api_group,
response_derives, struct_derives,
enum_derives,
} }
} }
@ -104,10 +110,18 @@ impl GroupGeneration {
self.name_camel() self.name_camel()
} }
pub fn response_derives(&self, additional_derives: Vec<&str>) -> TokenStream { pub fn struct_derives(&self) -> TokenStream {
self.derives(self.struct_derives, &[])
}
pub fn enum_derives(&self) -> TokenStream {
self.derives(self.enum_derives, &["PartialEq", "Eq"])
}
pub fn derives(&self, derives: &'a [&'a str], additional_derives: &[&str]) -> TokenStream {
let derives = self let derives = self
.all_derives() .all_derives(derives)
.chain(additional_derives.into_iter()) .chain(additional_derives.iter().copied())
.map(|s| syn::parse_str::<syn::Path>(s).unwrap()) .map(|s| syn::parse_str::<syn::Path>(s).unwrap())
.map(|derive| quote! { #derive }); .map(|derive| quote! { #derive });
@ -116,12 +130,11 @@ impl GroupGeneration {
} }
} }
fn all_derives(&self) -> impl Iterator<Item = &str> { fn all_derives(&self, derives: &'a [&'a str]) -> impl Iterator<Item = &'a str> {
let base = vec!["serde::Deserialize", "Debug"].into_iter(); let base = vec!["serde::Deserialize", "Debug"].into_iter();
let additional = self let additional = derives
.response_derives
.iter() .iter()
.map(|s| s.as_str()) .copied()
.filter(|item| item != &"serde::Deserialize") .filter(|item| item != &"serde::Deserialize")
.filter(|item| item != &"Debug"); .filter(|item| item != &"Debug");

View File

@ -5,12 +5,19 @@ use quote::quote;
use super::{api_group::GroupGeneration, util}; use super::{api_group::GroupGeneration, util};
pub fn generate_groups(groups: Vec<parser::ApiGroup>, resp_derives: Vec<String>) -> TokenStream { pub fn generate_groups(
groups: Vec<parser::ApiGroup>,
struct_derives: Vec<String>,
enum_derives: Vec<String>,
) -> TokenStream {
let struct_derives_borrowed: Vec<&str> = struct_derives.iter().map(|s| s.as_str()).collect();
let enum_derive_borrowed: Vec<&str> = enum_derives.iter().map(|s| s.as_str()).collect();
let gr = groups let gr = groups
.into_iter() .into_iter()
// implemented manually // implemented manually
.filter(|group| group.name != "authentication") .filter(|group| group.name != "authentication")
.map(|group| GroupGeneration::new(group, resp_derives.clone())) .map(|group| GroupGeneration::new(group, &struct_derives_borrowed, &enum_derive_borrowed))
.map(generate_group); .map(generate_group);
quote! { quote! {
@ -29,7 +36,7 @@ fn generate_group(group: GroupGeneration) -> TokenStream {
#[derive(Debug)] #[derive(Debug)]
pub struct StructGenerator<'a> { pub struct StructGenerator<'a> {
type_: &'a parser::TypeWithName, type_: &'a parser::TypeWithName,
group: &'a GroupGeneration, group: &'a GroupGeneration<'a>,
} }
impl<'a> StructGenerator<'a> { impl<'a> StructGenerator<'a> {
@ -44,7 +51,7 @@ impl<'a> StructGenerator<'a> {
.iter() .iter()
.map(|obj| obj.generate_struct_field()); .map(|obj| obj.generate_struct_field());
let name = util::to_ident(&self.type_.name); let name = util::to_ident(&self.type_.name);
let derives = self.group.response_derives(vec![]); let derives = self.group.struct_derives();
quote! { quote! {
#derives #derives
@ -109,7 +116,7 @@ impl types::Type {
#[derive(Debug)] #[derive(Debug)]
pub struct EnumGeneration<'a> { pub struct EnumGeneration<'a> {
enum_: &'a parser::Enum, enum_: &'a parser::Enum,
group: &'a GroupGeneration, group: &'a GroupGeneration<'a>,
} }
impl<'a> EnumGeneration<'a> { impl<'a> EnumGeneration<'a> {
@ -124,7 +131,7 @@ impl<'a> EnumGeneration<'a> {
.iter() .iter()
.map(|enum_value| enum_value.generate()); .map(|enum_value| enum_value.generate());
let name = util::to_ident(&self.enum_.name); let name = util::to_ident(&self.enum_.name);
let derives = self.group.response_derives(vec!["PartialEq", "Eq"]); let derives = self.group.enum_derives();
quote! { quote! {
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]

View File

@ -10,7 +10,7 @@ use super::{
#[derive(Debug)] #[derive(Debug)]
pub struct GroupMethod<'a> { pub struct GroupMethod<'a> {
group: &'a GroupGeneration, group: &'a GroupGeneration<'a>,
method: &'a parser::ApiMethod, method: &'a parser::ApiMethod,
} }
@ -116,7 +116,7 @@ impl<'a> GroupMethod<'a> {
.iter() .iter()
.map(|field| field.generate_struct_field()); .map(|field| field.generate_struct_field());
let derives = self.group.response_derives(vec![]); let derives = self.group.struct_derives();
quote! { quote! {
#derives #derives

View File

@ -15,13 +15,14 @@ use self::{group::generate_groups, skeleton::generate_skeleton};
pub fn generate(ast: &syn::DeriveInput, api_content: &str) -> TokenStream { pub fn generate(ast: &syn::DeriveInput, api_content: &str) -> TokenStream {
let ident = &ast.ident; let ident = &ast.ident;
let resp_derives = get_response_derives(ast); let struct_derives = get_derives(ast, "struct_derives");
let enum_derives = get_derives(ast, "enum_derives");
let token_tree = md_parser::TokenTreeFactory::create(api_content); let token_tree = md_parser::TokenTreeFactory::create(api_content);
let api_groups = parser::parse_api_groups(token_tree); let api_groups = parser::parse_api_groups(token_tree);
let skeleton = generate_skeleton(ident); let skeleton = generate_skeleton(ident);
let groups = generate_groups(api_groups, resp_derives); let groups = generate_groups(api_groups, struct_derives, enum_derives);
let impl_ident = syn::Ident::new(&format!("{}_impl", ident).to_snake(), ident.span()); let impl_ident = syn::Ident::new(&format!("{}_impl", ident).to_snake(), ident.span());
quote! { quote! {
@ -32,7 +33,7 @@ pub fn generate(ast: &syn::DeriveInput, api_content: &str) -> TokenStream {
} }
} }
fn get_response_derives(ast: &syn::DeriveInput) -> Vec<String> { fn get_derives(ast: &syn::DeriveInput, name: &str) -> Vec<String> {
ast.attrs ast.attrs
.iter() .iter()
.find(|attr| { .find(|attr| {
@ -53,9 +54,18 @@ fn get_response_derives(ast: &syn::DeriveInput) -> Vec<String> {
_ => None, _ => None,
}) })
.filter_map(|value| match value { .filter_map(|value| match value {
syn::Meta::NameValue(name_value) => Some(name_value.lit), syn::Meta::NameValue(name_value) => Some(name_value),
_ => None, _ => None,
}) })
.filter(|name_value| {
name_value
.path
.segments
.first()
.map(|seg| seg.ident == name)
.unwrap_or(false)
})
.map(|name_value| name_value.lit)
.filter_map(|lit| match lit { .filter_map(|lit| match lit {
syn::Lit::Str(str) => Some(str.value().split(',').map(|s| s.trim()).collect()), syn::Lit::Str(str) => Some(str.value().split(',').map(|s| s.trim()).collect()),
_ => None, _ => None,