use convert_case::{Case, Casing};
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote, ToTokens};
use syn::{punctuated::Punctuated, Ident, Token, Type};
use crate::{command_enum_parsing::Field, DataCommandEnum};
use super::get_input_type_of_bare_fn_field;
pub fn command_enum(input: &DataCommandEnum) -> TokenStream2 {
let (fields, namespace_enums): (TokenStream2, TokenStream2) =
turn_fields_to_enum(&input.fields);
quote! {
#[derive(Debug)]
pub enum Command {
#fields
}
#namespace_enums
}
}
fn turn_fields_to_enum(fields: &Punctuated<Field, Token![,]>) -> (TokenStream2, TokenStream2) {
let output: Vec<_> = fields
.iter()
.map(|field| turn_struct_field_to_enum(field))
.collect();
let mut fields_output: TokenStream2 = Default::default();
let mut namespace_enums_output: TokenStream2 = Default::default();
for (fields, namespace_enum) in output {
fields_output.extend(fields.to_token_stream());
namespace_enums_output.extend(namespace_enum.to_token_stream());
}
(fields_output, namespace_enums_output)
}
fn turn_struct_field_to_enum(field: &Field) -> (TokenStream2, TokenStream2) {
match field {
Field::Function(fun_field) => {
let field_name = format_ident!(
"{}",
fun_field
.name
.to_string()
.from_case(Case::Snake)
.to_case(Case::Pascal)
);
let input_type: Option<Type> = get_input_type_of_bare_fn_field(fun_field);
match input_type {
Some(input_type) => (
quote! {
#field_name(#input_type),
},
quote! {},
),
None => (
quote! {
#field_name,
},
quote! {},
),
}
}
Field::Namespace(namespace) => {
let (namespace_output_fields, namespace_output_namespace_enums) =
turn_fields_to_enum(&namespace.fields);
let namespace_name: Ident = format_ident!(
"{}",
namespace
.path
.iter()
.map(|name| name.to_string())
.collect::<String>()
);
let new_namespace_name: Ident = format_ident!(
"{}",
namespace_name
.to_string()
.from_case(Case::Snake)
.to_case(Case::Pascal)
);
(
quote! {
#new_namespace_name(#new_namespace_name),
},
quote! {
#[derive(Debug)]
pub enum #new_namespace_name {
#namespace_output_fields
}
#namespace_output_namespace_enums
},
)
}
}
}