use crate::utils;
use quote::ToTokens;
mod kw {
syn::custom_keyword!(to);
}
#[derive(Debug, Clone)]
pub struct Delegate {
pub functions: Vec<syn::ImplItemFn>
}
impl syn::parse::Parse for Delegate {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut functions = Vec::new();
while !input.is_empty() {
input.parse::<kw::to>()?;
let delegate_to = input.parse::<syn::ExprField>()?;
let content;
let _brace_token = syn::braced!(content in input);
while !content.is_empty() {
let fn_item = content.parse::<syn::TraitItemFn>()?;
let fn_ident = fn_item.sig.ident.clone();
let args = utils::syn::function_typed_args(&fn_item.sig);
let args = args
.iter()
.filter_map(|ty| match &*ty.pat {
syn::Pat::Ident(pat) => Some(pat.ident.clone()),
_ => None
})
.collect::<syn::punctuated::Punctuated<syn::Ident, syn::Token![,]>>();
let mut attrs = fn_item.attrs.clone();
if utils::syn::docs_attrs(&attrs).is_empty() {
let comment = format!(
" Delegated. See `{}.{}.{}()` for details.",
delegate_to.base.to_token_stream(),
delegate_to.member.to_token_stream(),
fn_ident
);
let attr = syn::parse_quote!(#[doc = #comment]);
attrs.push(attr);
}
functions.push(syn::ImplItemFn {
attrs,
vis: utils::syn::visibility_pub(),
defaultness: None,
sig: fn_item.sig,
block: syn::parse_quote!({ #delegate_to.#fn_ident(#args) })
});
}
}
Ok(Self { functions })
}
}