use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::{parse2, Attribute, ItemConst, Result};
pub fn expand(_attr: TokenStream, item: TokenStream) -> Result<TokenStream> {
let original: ItemConst = parse2(item)?;
let name_ident = &original.ident;
let name_str = name_ident.to_string();
let ty = &original.ty;
let expr = &original.expr;
let ty_str = quote!(#ty).to_string();
let value_str = quote!(#expr).to_string();
let docs_str = collect_doc_comments(&original.attrs);
let descriptor_ident = format_ident!("__HOPPER_CONST_{}", name_ident);
Ok(quote! {
#original
#[doc(hidden)]
#[allow(non_upper_case_globals, non_snake_case)]
pub const #descriptor_ident: ::hopper::hopper_schema::ConstantDescriptor =
::hopper::hopper_schema::ConstantDescriptor {
name: #name_str,
ty: #ty_str,
value: #value_str,
docs: #docs_str,
};
})
}
fn collect_doc_comments(attrs: &[Attribute]) -> String {
let mut out = String::new();
for attr in attrs {
if !attr.path().is_ident("doc") {
continue;
}
if let syn::Meta::NameValue(nv) = &attr.meta {
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(s),
..
}) = &nv.value
{
if !out.is_empty() {
out.push('\n');
}
out.push_str(s.value().trim());
}
}
}
out
}