async-trait-ext 0.2.1

a procedural macro for async traits
Documentation
use crate::{
    ext_trait_name,
    input::TraitInput,
    methods::{
        CleanUpMutPatternsExpand, ExtMethodExpand, FutureAliasExpand, FutureStructExpand,
        ImplFutureExpand, PollMethodExpand,
    },
};
use macro_compose::{Collector, Context, Expand};
use syn::{parse_quote, ItemTrait, TraitItem};

pub struct PollTraitExpand;

impl Expand<ItemTrait> for PollTraitExpand {
    type Output = ItemTrait;

    fn expand(&self, input: &ItemTrait, c: &mut Collector) -> Option<Self::Output> {
        let mut item = input.clone();

        item.items = item
            .items
            .into_iter()
            .filter_map(|item| {
                if let TraitItem::Method(m) = item {
                    let mut subcontext = Context::new(c, m);
                    let method = subcontext.capture(&PollMethodExpand(input))?;

                    let mut subcontext = Context::new(c, method);

                    Some(TraitItem::Method(
                        subcontext.capture(&CleanUpMutPatternsExpand)?,
                    ))
                } else {
                    Some(item)
                }
            })
            .collect();

        for item in item.items.iter_mut() {
            if let TraitItem::Method(m) = item {
                let mut subcontext = Context::new_by_ref(c, m);

                if let Some(res) = subcontext.capture(&PollMethodExpand(input)) {
                    *m = res;
                }
            }
        }

        TraitInput::strip(&mut item.attrs);

        Some(item)
    }
}

pub struct ExtensionTraitExpand;

impl Expand<ItemTrait> for ExtensionTraitExpand {
    type Output = ItemTrait;

    fn expand(&self, input: &ItemTrait, c: &mut Collector) -> Option<Self::Output> {
        let mut item = input.clone();
        item.ident = ext_trait_name(input);

        let ident = &input.ident;
        item.supertraits.push(parse_quote!(#ident));

        let attrs = TraitInput::from(item.attrs.as_slice());
        if attrs.dynamic.is_none() {
            item.supertraits.push(parse_quote!(::core::marker::Sized));
        }

        item.items = item
            .items
            .into_iter()
            .filter_map(|item| {
                if let TraitItem::Method(m) = item {
                    let mut subcontext = Context::new(c, m);

                    subcontext.expand(&FutureStructExpand(input));
                    subcontext.expand(&ImplFutureExpand(input));
                    subcontext.expand(&FutureAliasExpand(input));

                    let method = subcontext.capture(&ExtMethodExpand(input))?;
                    let mut subcontext = Context::new(c, method);
                    subcontext
                        .capture(&CleanUpMutPatternsExpand)
                        .map(TraitItem::Method)
                } else {
                    None
                }
            })
            .collect();

        TraitInput::strip(&mut item.attrs);

        Some(item)
    }
}