use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::Type;
use crate::attrs::{ContainerAttrs, RenameAll};
#[derive(Debug, Clone)]
pub struct ProxyConfig {
pub target: Type,
pub is_opaque: bool,
}
pub struct MacroConfig {
pub document_crate: TokenStream,
pub rename_all: Option<RenameAll>,
pub rename_all_fields: Option<RenameAll>,
pub parse_error: Option<TokenStream>,
pub write_error: Option<TokenStream>,
pub type_name: Option<String>,
pub non_exhaustive: bool,
pub proxy: Option<ProxyConfig>,
pub opaque_span: Option<Span>,
}
impl MacroConfig {
pub fn from_attrs(
attrs: ContainerAttrs,
attr_spans: std::collections::HashMap<String, Span>,
) -> syn::Result<Self> {
use quote::ToTokens;
let document_crate = attrs
.crate_path
.map(|path| path.into_token_stream())
.unwrap_or_else(|| quote! { ::eure::document });
let parse_error = attrs.parse_error.map(|path| path.into_token_stream());
let write_error = attrs.write_error.map(|path| path.into_token_stream());
if attrs.proxy.is_some() && attrs.opaque.is_some() {
let span = attr_spans
.get("proxy")
.or_else(|| attr_spans.get("opaque"))
.copied()
.unwrap_or_else(Span::call_site);
return Err(syn::Error::new(
span,
"cannot use both #[eure(proxy = \"...\")] and #[eure(opaque = \"...\")] on the same type; they are mutually exclusive",
));
}
let proxy = attrs
.proxy
.map(|target| ProxyConfig {
target,
is_opaque: false,
})
.or_else(|| {
attrs.opaque.map(|target| ProxyConfig {
target,
is_opaque: true,
})
});
Ok(Self {
document_crate,
rename_all: attrs.rename_all,
rename_all_fields: attrs.rename_all_fields,
parse_error,
write_error,
type_name: attrs.type_name,
non_exhaustive: attrs.non_exhaustive,
proxy,
opaque_span: attr_spans.get("opaque").copied(),
})
}
}