ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use std::fmt::{Debug, Display, Formatter};
use proc_macro2::Ident;
use quote::ToTokens;
use syn::{Generics, Lifetime, Path, TraitBound, Type, TypePtr, TypeReference, TypeTraitObject};
use crate::composable::{NestedArgument, TypeModeled};
use crate::composer::CommaPunctuatedNestedArguments;
use crate::context::ScopeChain;
use crate::ext::{AsType, refine_ty_with_import_path, RefineWithNestedArgs, ToPath, ToType, LifetimeProcessor, ArgsTransform, MaybeTraitBound};

#[derive(Clone)]
pub struct TypeModel {
    pub ty: Type,
    pub generics: Option<Generics>,
    pub nested_arguments: CommaPunctuatedNestedArguments,
}

impl TypeModeled for TypeModel {
    fn type_model_mut(&mut self) -> &mut TypeModel {
        self
    }

    fn type_model_ref(&self) -> &TypeModel {
        self
    }
}

impl From<&Type> for TypeModel {
    fn from(value: &Type) -> Self {
        Self::new_default(value.clone())
    }
}
impl From<Type> for TypeModel {
    fn from(value: Type) -> Self {
        Self::new_default(value)
    }
}

impl TypeModel {
    fn new(ty: Type, generics: Option<Generics>, nested_arguments: CommaPunctuatedNestedArguments) -> Self {
        Self { ty, generics, nested_arguments }
    }
    pub fn new_default(ty: Type) -> Self {
        Self::new(ty, None, CommaPunctuatedNestedArguments::new())
    }
    pub fn new_default_from_path(path: &Path) -> Self {
        Self::new(path.to_type(), None, CommaPunctuatedNestedArguments::new())
    }
    pub fn new_default_from_trait_bound(trait_bound: &TraitBound) -> Self {
        Self::new_default_from_path(&trait_bound.path)
    }
    pub fn new_nested(ty: Type, nested_arguments: CommaPunctuatedNestedArguments) -> Self {
        Self::new(ty, None, nested_arguments)
    }
    pub fn new_nested_ref(ty: &Type, nested_arguments: CommaPunctuatedNestedArguments) -> Self {
        Self::new_nested(ty.clone(), nested_arguments)
    }
    pub fn new_generic(ty: Type, generics: Generics, nested_arguments: CommaPunctuatedNestedArguments) -> Self {
        Self::new(ty, Some(generics), nested_arguments)
    }
    pub fn new_generic_ident(ident: &Ident, generics: Generics, nested_arguments: CommaPunctuatedNestedArguments) -> Self {
        Self::new_generic(ident.to_type(), generics, nested_arguments)
    }
    pub fn new_generic_non_nested(ty: Type, generics: &Generics) -> Self {
        Self::new(ty, Some(generics.clone()), CommaPunctuatedNestedArguments::new())
    }
    pub fn new_generic_ident_non_nested(ident: &Ident, generics: &Generics) -> Self {
        Self::new_generic_non_nested(ident.to_type(), generics)
    }
    pub fn new_generic_scope_non_nested(scope: &ScopeChain, generics: &Generics) -> Self {
        Self::new_generic_non_nested(scope.to_type(), generics)
    }
    pub fn new_generic_scope(scope: &ScopeChain, generics: &Generics, nested_arguments: CommaPunctuatedNestedArguments) -> Self {
        Self::new_generic(scope.to_type(), generics.clone(), nested_arguments)
    }
}
impl TypeModel {
    pub fn first_nested_argument(&self) -> Option<&NestedArgument> {
        self.nested_arguments_ref().first()
    }
    pub fn refine(&mut self, import_path: &Path) {
        let _ = self.ty.refine_with_nested_args(&self.nested_arguments);
        let _ = refine_ty_with_import_path(&mut self.ty, import_path);
    }
    pub fn nested_argument_at_index(&self, index: usize) -> &NestedArgument {
        &self.nested_arguments[index]
    }

    pub fn pointer_less(&self) -> Path {
        match &self.ty {
            Type::Reference(TypeReference { elem, .. }) |
            Type::Ptr(TypePtr { elem, .. }) => elem.to_path(),
            Type::TraitObject(TypeTraitObject { bounds, .. }) =>
                bounds.iter()
                    .find_map(MaybeTraitBound::maybe_trait_bound)
                    .map(|TraitBound { path, .. }| path.arg_less())
                    .unwrap_or_else(|| bounds.to_path()),
            other =>
                other.to_path()
        }
    }
}

impl LifetimeProcessor for TypeModel {
    fn clean_lifetimes(&mut self) {
        self.ty.clean_lifetimes();
    }

    fn unique_lifetimes(&self) -> Vec<Lifetime> {
        self.ty.unique_lifetimes()
    }
}

impl<'a> AsType<'a> for TypeModel {
    fn as_type(&'a self) -> &'a Type {
        &self.ty
    }
}

impl ToType for TypeModel {
    fn to_type(&self) -> Type {
        self.as_type().clone()
    }
}

impl Debug for TypeModel {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("$Ty({}, {:?})", self.ty.to_token_stream(), self.nested_arguments))
    }
}

impl Display for TypeModel {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        std::fmt::Debug::fmt(self, f)
    }
}