ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::vec;
use proc_macro2::Ident;
use syn::{Generics, ItemTrait, TraitItem, TraitItemFn, Lifetime};
use ferment_macro::ComposerBase;
use crate::composable::{AttrsModel, FnSignatureContext, GenModel, LifetimesModel, TraitTypeModel};
use crate::composer::{BasicComposer, BasicComposerLink, BasicComposerOwner, ComposerLink, DocComposer, DocsComposable, Linkable, SigComposer, SigComposerLink, SourceAccessible, SourceComposable};
use crate::context::{ScopeChain, ScopeContextLink};
use crate::ext::{Join, ToType};
use crate::lang::Specification;
use crate::presentable::NameTreeContext;
use crate::presentation::DocPresentation;

#[derive(ComposerBase)]
pub struct TraitComposer<SPEC>
    where SPEC: Specification + 'static {
    pub base: BasicComposerLink<SPEC, Self>,
    pub methods: Vec<SigComposerLink<SPEC>>,
    #[allow(unused)]
    pub types: HashMap<Ident, TraitTypeModel>,
}

impl<SPEC> TraitComposer<SPEC>
    where SPEC: Specification {
    pub fn from_item_trait(
        item_trait: &ItemTrait,
        ty_context: SPEC::TYC,
        scope: &ScopeChain,
        scope_context: &ScopeContextLink) -> ComposerLink<Self> {
        let ItemTrait { attrs, generics, ident, items,  .. } = item_trait;
        let self_ty = ident.to_type();
        let source = scope_context.borrow();
        let mut methods = vec![];
        let mut types = HashMap::new();
        items
            .iter()
            .for_each(|trait_item| match trait_item {
                TraitItem::Fn(trait_item_method) => {
                    let TraitItemFn { sig, attrs, .. } = trait_item_method;
                    let sig_context = FnSignatureContext::TraitInner(sig.clone(), self_ty.clone(), self_ty.clone());
                    let method_scope_context = Rc::new(RefCell::new(source.joined(trait_item_method)));
                    let ty_context = ty_context.join_fn(
                        scope.joined_path(&sig.ident),
                        sig_context,
                        attrs.clone());
                    methods.push(SigComposer::from_trait_item_method(trait_item_method, ty_context, &method_scope_context));
                },
                TraitItem::Type(trait_item_type) => {
                    types.insert(trait_item_type.ident.clone(), TraitTypeModel::from_item_type(trait_item_type));
                },
                _ => {}
            });
        Self::new(
            methods,
            types,
            ty_context,
            Some(generics.clone()),
            vec![],
            AttrsModel::from(attrs),
            scope_context)
    }

    fn new(
        methods: Vec<SigComposerLink<SPEC>>,
        types: HashMap<Ident, TraitTypeModel>,
        ty_context: SPEC::TYC,
        generics: Option<Generics>,
        lifetimes: Vec<Lifetime>,
        attrs: AttrsModel,
        context: &ScopeContextLink
    ) -> ComposerLink<Self> {
        let root = Rc::new(RefCell::new(Self {
            base: BasicComposer::from(DocComposer::from(&ty_context), attrs, ty_context, GenModel::new(generics), LifetimesModel::new(lifetimes), Rc::clone(context)),
            methods,
            types,
        }));
        {
            let mut composer = root.borrow_mut();
            composer.base.link(&root);
        }
        root
    }
}

impl<SPEC> DocsComposable for TraitComposer<SPEC>
    where SPEC: Specification {
    fn compose_docs(&self) -> DocPresentation {
        DocPresentation::Direct(self.base.doc.compose(self.context()))
    }
}