fieldx_core 0.2.3

Various types and tools useful implementing fieldx_derive core functionality. May provide useful APIs for 3rd-party crates.
Documentation
pub mod field;
pub mod r#fn;
pub mod r#impl;
pub mod r#struct;

use fieldx_aux::FXProp;
use proc_macro2::TokenStream;
use quote::quote;
use quote::quote_spanned;
use quote::ToTokens;

pub use field::*;
pub use r#fn::*;
pub use r#impl::*;
pub use r#struct::*;

macro_rules! tokenstream_setter {
    ( $($name:ident),+ $(,)? ) => {
        $(
            ::paste::paste! {
                pub fn [<set_ $name>]<T: ToTokens>(&mut self, value: T) -> &mut Self {
                    let tt = value.to_token_stream();
                    self.$name = if tt.is_empty() {
                        None
                    }
                    else {
                        Some(value.to_token_stream())
                    };
                    self
                }
            }
        )+
    }
}

pub(crate) use tokenstream_setter;

use crate::ctx::Attributizer;

pub trait FXConstructor {
    fn fx_to_tokens(&self) -> TokenStream;
    fn set_span(&mut self, span: proc_macro2::Span) -> &mut Self;
    fn add_attribute(&mut self, attribute: syn::Attribute) -> &mut Self;

    fn split_generics(&self, generics: Option<&syn::Generics>) -> (TokenStream, TokenStream, TokenStream) {
        generics.map_or_else(
            || (quote![], quote![], quote![]),
            |g| {
                let split = g.split_for_impl();
                (
                    split.0.to_token_stream(),
                    split.1.to_token_stream(),
                    split.2.to_token_stream(),
                )
            },
        )
    }

    fn add_attributes<'a, A: Into<&'a syn::Attribute>, I: Iterator<Item = A>>(
        &'a mut self,
        attributes: I,
    ) -> &'a mut Self {
        for attribute in attributes {
            self.add_attribute(attribute.into().clone());
        }
        self
    }

    fn maybe_add_attributes<'a, A: Into<&'a syn::Attribute>, I: Iterator<Item = A>>(
        &'a mut self,
        attributes: Option<I>,
    ) -> &'a mut Self {
        if let Some(attributes) = attributes {
            self.add_attributes(attributes.map(|a| a.into()))
        }
        else {
            self
        }
    }

    fn add_attribute_toks<T>(&mut self, attribute: T) -> darling::Result<&mut Self>
    where
        T: ToTokens,
    {
        let attributes = Attributizer::parse(attribute.to_token_stream())?.into_inner();
        for attribute in attributes {
            self.add_attribute(attribute);
        }
        Ok(self)
    }

    fn add_doc(&mut self, literals: &FXProp<Vec<syn::LitStr>>) -> darling::Result<&mut Self> {
        let lits = literals.value();
        self.add_attributes(
            Attributizer::parse(quote_spanned! {literals.final_span()=>  #( #[doc = #lits] )* })?
                .into_inner()
                .iter(),
        );
        Ok(self)
    }

    #[inline]
    fn maybe_add_doc(&mut self, literals: Option<&FXProp<Vec<syn::LitStr>>>) -> darling::Result<&mut Self> {
        if let Some(literals) = literals {
            self.add_doc(literals)?;
        }
        Ok(self)
    }
}