use proc_macro2::TokenStream;
use quote::quote;
use super::helpers::{build_transparent_pattern, build_variant_pattern};
use crate::ir::{EnumDefinition, VariantDefinition};
pub fn generate_error_impl(ir: &EnumDefinition) -> TokenStream {
let name = &ir.name;
let (impl_generics, ty_generics, where_clause) = ir.generics.split_for_impl();
let source_arms: Vec<TokenStream> = ir
.variants
.iter()
.flat_map(|variant| {
match variant {
VariantDefinition::Regular(regular) => {
let variant_name = ®ular.name;
let pattern = build_variant_pattern(regular);
let source_field = regular.fields.iter().find(|f| f.is_source);
let arm = if let Some(field) = source_field {
let field_name = &field.rust_name;
quote! {
Self::#variant_name #pattern => {
{
use ::apollo_errors::private::AsDynError as _;
::std::option::Option::Some(#field_name.as_dyn_error())
}
}
}
} else {
quote! {
Self::#variant_name #pattern => {
::std::option::Option::None
}
}
};
vec![arm]
}
VariantDefinition::Transparent(transparent) => {
let variant_name = &transparent.name;
let pattern = build_transparent_pattern(transparent);
vec![quote! {
Self::#variant_name #pattern => {
::std::option::Option::Some(inner as &(dyn ::std::error::Error + 'static))
}
}]
}
}
})
.collect();
quote! {
#[automatically_derived]
impl #impl_generics ::std::error::Error for #name #ty_generics #where_clause {
fn source(&self) -> ::std::option::Option<&(dyn ::std::error::Error + 'static)> {
match self {
#(#source_arms)*
}
}
}
}
}