fieldx_core 0.2.3

Various types and tools useful implementing fieldx_derive core functionality. May provide useful APIs for 3rd-party crates.
Documentation
use getset::Getters;
use proc_macro2::Span;
use proc_macro2::TokenStream;
use quote::quote_spanned;
use quote::ToTokens;

use crate::field_receiver::FXField;

use super::FXConstructor;

#[derive(Debug, Getters)]
#[getset(get = "pub")]
pub struct FXFieldConstructor {
    ident:      syn::Ident,
    ty:         TokenStream,
    vis:        Option<TokenStream>,
    attributes: Vec<syn::Attribute>,
    span:       Option<Span>,
}

impl FXFieldConstructor {
    #[inline]
    pub fn new<T: ToTokens>(ident: syn::Ident, ty: T, span: Span) -> Self {
        Self {
            ident,
            ty: ty.to_token_stream(),
            vis: None,
            attributes: Vec::new(),
            span: Some(span),
        }
    }

    #[inline]
    pub fn set_vis<T: ToTokens>(&mut self, vis: T) -> &mut Self {
        self.vis = Some(vis.to_token_stream());
        self
    }

    #[inline]
    pub fn set_type<T: ToTokens>(&mut self, ty: T) -> &mut Self {
        self.ty = ty.to_token_stream();
        self
    }
}

impl FXConstructor for FXFieldConstructor {
    fn fx_to_tokens(&self) -> TokenStream {
        let vis = self.vis.as_ref();
        let attributes = &self.attributes;
        let ident = &self.ident;
        let ty = &self.ty;
        #[allow(clippy::redundant_closure)]
        let span = self.span.unwrap_or_else(|| Span::call_site());

        quote_spanned! {span=>
            #(#attributes)*
            #vis #ident: #ty
        }
    }

    fn set_span(&mut self, span: proc_macro2::Span) -> &mut Self {
        self.span = Some(span);
        self
    }

    #[inline]
    fn add_attribute(&mut self, attribute: syn::Attribute) -> &mut Self {
        self.attributes.push(attribute);
        self
    }
}

impl ToTokens for FXFieldConstructor {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.extend(self.fx_to_tokens());
    }
}

impl TryFrom<&FXField> for FXFieldConstructor {
    type Error = darling::Error;

    fn try_from(field: &FXField) -> darling::Result<Self> {
        let vis = field.vis().to_token_stream();
        let vis = if vis.is_empty() { None } else { Some(vis) };
        let mut fc = Self {
            ident: field.ident()?,
            ty: field.ty().to_token_stream(),
            attributes: field.attrs().clone(),
            span: Some(field.span()),
            vis,
        };

        fc.add_attributes(field.fieldx_attrs().iter());

        Ok(fc)
    }
}