use std::collections::HashMap;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::{ItemEnum, ItemTrait, Path};
use crate::error::InvalidInput;
use crate::generate;
use crate::generate::enum_conversion::generate_enum_conversions;
use crate::generate::{delegate_trait_for_enum, helper_mod};
use crate::input::associated_type::parse_associated_type_configurations;
use crate::input::single_field_enum::{parse_enum_variants, SingleFieldEnum};
use crate::input::AssociatedTypeUnification;
pub struct DelegationOptions {
pub generate_from_into_conversions: bool,
}
impl Default for DelegationOptions {
fn default() -> Self {
Self {
generate_from_into_conversions: true,
}
}
}
pub fn implement_delegation(
trait_path: &Path,
parsed_trait: &ItemTrait,
enum_path: &Path,
original_enum: &ItemEnum,
options: DelegationOptions,
) -> Result<TokenStream, InvalidInput> {
let associated_type_config = parse_associated_type_configurations(parsed_trait)?;
let helper_mod_name = helper_mod::helper_mod_name(parsed_trait, original_enum);
let helper_mod = helper_mod::generate_helper_mod(&helper_mod_name);
let associated_type_enum_names =
generate::enum_definitions::generate_associated_type_enum_names(
parsed_trait,
&associated_type_config,
original_enum,
);
let context = MacroContext {
options,
trait_path,
parsed_trait,
associated_type_config,
associated_type_enum_names,
enum_path,
parsed_enum: parse_enum_variants(original_enum)?,
helper_mod_name,
};
let enum_definitions = generate::enum_definitions::generate_enum_definitions(&context);
let main_enum_conversions = context
.options
.generate_from_into_conversions
.then(|| generate_enum_conversions(context.enum_path, &context.parsed_enum));
let trait_impl = delegate_trait_for_enum::generate_trait_impl(&context)?;
Ok(quote! {
#helper_mod
#enum_definitions
#main_enum_conversions
#trait_impl
})
}
pub(crate) struct MacroContext<'a> {
pub options: DelegationOptions,
pub trait_path: &'a Path,
pub parsed_trait: &'a ItemTrait,
pub associated_type_config: HashMap<Ident, AssociatedTypeUnification>,
pub associated_type_enum_names: HashMap<Ident, Ident>,
pub enum_path: &'a Path,
pub parsed_enum: SingleFieldEnum,
pub helper_mod_name: Ident,
}