alloy_sol_macro_expander/expand/
error.rs
1use super::{expand_fields, expand_from_into_tuples, expand_tokenize, ExpCtxt};
4use alloy_sol_macro_input::{mk_doc, ContainsSolAttrs};
5use ast::ItemError;
6use proc_macro2::TokenStream;
7use quote::quote;
8use syn::Result;
9
10pub(super) fn expand(cx: &ExpCtxt<'_>, error: &ItemError) -> Result<TokenStream> {
22 let ItemError { parameters: params, .. } = error;
23 cx.assert_resolved(params)?;
24
25 let (sol_attrs, mut attrs) = error.split_attrs()?;
26 cx.derives(&mut attrs, params, true);
27 let docs = sol_attrs.docs.or(cx.attrs.docs).unwrap_or(true);
28 let abi = sol_attrs.abi.or(cx.attrs.abi).unwrap_or(false);
29
30 let tokenize_impl = expand_tokenize(params, cx);
31
32 let name = cx.overloaded_name(error.into());
33 let signature = cx.error_signature(error);
34 let selector = crate::utils::selector(&signature);
35
36 let alloy_sol_types = &cx.crates.sol_types;
37
38 let converts = expand_from_into_tuples(&name.0, params, cx);
39 let fields = expand_fields(params, cx);
40 let doc = docs.then(|| {
41 let selector = hex::encode_prefixed(selector.array.as_slice());
42 mk_doc(format!(
43 "Custom error with signature `{signature}` and selector `{selector}`.\n\
44 ```solidity\n{error}\n```"
45 ))
46 });
47 let abi: Option<TokenStream> = abi.then(|| {
48 if_json! {
49 let error = super::to_abi::generate(error, cx);
50 quote! {
51 #[automatically_derived]
52 impl alloy_sol_types::JsonAbiExt for #name {
53 type Abi = alloy_sol_types::private::alloy_json_abi::Error;
54
55 #[inline]
56 fn abi() -> Self::Abi {
57 #error
58 }
59 }
60 }
61 }
62 });
63 let tokens = quote! {
64 #(#attrs)*
65 #doc
66 #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)]
67 #[derive(Clone)]
68 pub struct #name {
69 #(#fields),*
70 }
71
72 #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields, clippy::style)]
73 const _: () = {
74 use #alloy_sol_types as alloy_sol_types;
75
76 #converts
77
78 #[automatically_derived]
79 impl alloy_sol_types::SolError for #name {
80 type Parameters<'a> = UnderlyingSolTuple<'a>;
81 type Token<'a> = <Self::Parameters<'a> as alloy_sol_types::SolType>::Token<'a>;
82
83 const SIGNATURE: &'static str = #signature;
84 const SELECTOR: [u8; 4] = #selector;
85
86 #[inline]
87 fn new<'a>(tuple: <Self::Parameters<'a> as alloy_sol_types::SolType>::RustType) -> Self {
88 tuple.into()
89 }
90
91 #[inline]
92 fn tokenize(&self) -> Self::Token<'_> {
93 #tokenize_impl
94 }
95 }
96
97 #abi
98 };
99 };
100 Ok(tokens)
101}