use proc_macro2::TokenStream;
use quote::quote;
use crate::codegen::helpers::{
DEFAULT_JSONRPC_CODE, generate_downcast_attempts, generate_field_metadata, quote_option_str,
};
use crate::ir::StructDefinition;
pub fn generate_registry_entry(ir: &StructDefinition) -> TokenStream {
let private = quote!(::apollo_errors::private);
let linkme_crate = quote!(#private::linkme);
let serde_json_crate = quote!(#private::serde_json);
let name = &ir.name;
let name_str = name.to_string();
let message = &ir.error_message;
let code = &ir.diagnostic_code;
let http_status = ir.http_status.unwrap_or(500);
let jsonrpc_code = ir.jsonrpc_code.unwrap_or(DEFAULT_JSONRPC_CODE);
let static_prefix = format!("_APOLLO_ERROR_{}", name_str.to_uppercase());
let static_name = syn::Ident::new(&format!("{static_prefix}_REGISTRY_ENTRY"), name.span());
let fields_static_name = syn::Ident::new(&format!("{static_prefix}_FIELDS"), name.span());
let variants_static_name = syn::Ident::new(&format!("{static_prefix}_VARIANTS"), name.span());
let metadata_static_name = syn::Ident::new(&format!("{static_prefix}_METADATA"), name.span());
let field_metadata: Vec<_> = ir.fields.iter().map(generate_field_metadata).collect();
let help = quote_option_str(&ir.help_text);
let url = quote_option_str(&ir.url);
let severity = quote_option_str(&ir.severity);
let render_json_fn = syn::Ident::new(
&format!("{}_render_json", static_prefix.to_lowercase()),
name.span(),
);
let render_debug_fn = syn::Ident::new(
&format!("{}_render_debug", static_prefix.to_lowercase()),
name.span(),
);
let render_html_fn = syn::Ident::new(
&format!("{}_render_html", static_prefix.to_lowercase()),
name.span(),
);
let render_graphql_fn = syn::Ident::new(
&format!("{}_render_graphql", static_prefix.to_lowercase()),
name.span(),
);
let render_text_fn = syn::Ident::new(
&format!("{}_render_text", static_prefix.to_lowercase()),
name.span(),
);
let http_status_fn = syn::Ident::new(
&format!("{}_http_status", static_prefix.to_lowercase()),
name.span(),
);
let render_jsonrpc_fn = syn::Ident::new(
&format!("{}_render_jsonrpc", static_prefix.to_lowercase()),
name.span(),
);
let http_headers_fn = syn::Ident::new(
&format!("{}_http_headers", static_prefix.to_lowercase()),
name.span(),
);
let json_body = generate_downcast_attempts(name, "to_json");
let debug_body = generate_downcast_attempts(name, "to_debug");
let html_body = generate_downcast_attempts(name, "to_html");
let graphql_body = generate_downcast_attempts(name, "to_graphql");
let text_body = generate_downcast_attempts(name, "to_text");
let http_status_body = generate_downcast_attempts(name, "http_status");
let jsonrpc_body = generate_downcast_attempts(name, "to_jsonrpc");
let http_headers_body = generate_downcast_attempts(name, "http_headers");
quote! {
static #fields_static_name: &[::apollo_errors::private::FieldMetadata] = &[
#(#field_metadata),*
];
static #variants_static_name: &[::apollo_errors::private::VariantMetadata] = &[
::apollo_errors::private::VariantMetadata::Regular(
::apollo_errors::private::RegularVariantMetadata {
name: #name_str,
message: #message,
code: #code,
http_status: #http_status,
jsonrpc_code: #jsonrpc_code,
help: #help,
url: #url,
severity: #severity,
fields: #fields_static_name,
}
)
];
static #metadata_static_name: ::apollo_errors::private::ErrorMetadata =
::apollo_errors::private::ErrorMetadata {
type_name: #name_str,
variants: #variants_static_name,
};
fn #render_json_fn(error: &(dyn std::error::Error + 'static)) -> Option<::std::result::Result<#serde_json_crate::Value, #serde_json_crate::Error>> {
#json_body
}
fn #render_debug_fn(error: &(dyn std::error::Error + 'static)) -> Option<String> {
#debug_body
}
fn #render_html_fn(error: &(dyn std::error::Error + 'static)) -> Option<String> {
#html_body
}
fn #render_graphql_fn(error: &(dyn std::error::Error + 'static)) -> Option<::std::result::Result<#serde_json_crate::Value, #serde_json_crate::Error>> {
#graphql_body
}
fn #render_text_fn(error: &(dyn std::error::Error + 'static)) -> Option<String> {
#text_body
}
fn #http_status_fn(error: &(dyn std::error::Error + 'static)) -> Option<::apollo_errors::http::StatusCode> {
#http_status_body
}
fn #render_jsonrpc_fn(error: &(dyn std::error::Error + 'static)) -> Option<::std::result::Result<#serde_json_crate::Value, #serde_json_crate::Error>> {
#jsonrpc_body
}
fn #http_headers_fn(error: &(dyn std::error::Error + 'static)) -> Option<Vec<(::apollo_errors::http::HeaderName, ::apollo_errors::http::HeaderValue)>> {
#http_headers_body
}
#[#linkme_crate::distributed_slice(::apollo_errors::private::ERROR_REGISTRY)]
#[linkme(crate = #linkme_crate)]
#[doc(hidden)]
static #static_name: ::apollo_errors::private::ErrorRegistryEntry =
::apollo_errors::private::ErrorRegistryEntry {
type_id: std::any::TypeId::of::<#name>(),
type_name: #name_str,
metadata: &#metadata_static_name,
render_json: #render_json_fn,
render_debug: #render_debug_fn,
render_html: #render_html_fn,
render_graphql: #render_graphql_fn,
render_text: #render_text_fn,
http_status: #http_status_fn,
render_jsonrpc: #render_jsonrpc_fn,
http_headers: #http_headers_fn,
};
}
}