macro_tools 0.85.0

Tools for writing procedural macroses.
Documentation
//!
//! Advanced syntax elements.
//!

/// Define a private namespace for all its items.
mod private 
{

  use crate :: *;
  use interval_adapter ::BoundExt;

  /// Check is the rightmost item of path refering a type is specified type.
  ///
  /// Good to verify `core ::option ::Option< i32 >` is optional.
  /// Good to verify `alloc ::vec ::Vec< i32 >` is vector.
  ///
  /// ### Basic use-case.
  /// ```rust
  /// use macro_tools ::exposed :: *;
  ///
  /// let code = qt!( core ::option ::Option< i32 > );
  /// let tree_type = syn ::parse2 :: < syn ::Type >( code ).unwrap();
  /// let got = typ ::type_rightmost( &tree_type );
  /// assert_eq!( got, Some( "Option".to_string() ) );
  /// ```
  /// # Panics
  /// qqq: doc
  #[ must_use ]
  pub fn type_rightmost(ty: &syn ::Type) -> Option< String >
  {
  if let syn ::Type ::Path(path) = ty 
  {
   let last = &path.path.segments.last();
   if last.is_none() 
   {
  return None;
 }
   return Some(last.unwrap().ident.to_string());
 }
  None
 }

  /// Return the specified number of parameters of the type.
  ///
  /// Good to getting `i32` from `core ::option ::Option< i32 >` or `alloc ::vec ::Vec< i32 >`
  ///
  /// ### Basic use-case.
  /// ```
  /// use macro_tools :: { typ, qt };
  ///
  /// let code = qt!( core ::option ::Option< i8, i16, i32, i64 > );
  /// let tree_type = syn ::parse2 :: < syn ::Type >( code ).unwrap();
  /// let got = typ ::type_parameters( &tree_type, 0..=2 );
  /// got.iter().for_each( | e | println!( "{}", qt!( #e ) ) );
  /// // < i8
  /// // < i16
  /// // < i32
  /// ```
  /// # Panics
  /// qqq: doc
  #[ allow( clippy ::cast_possible_wrap, clippy ::needless_pass_by_value ) ]
  pub fn type_parameters(ty: &syn ::Type, range: impl NonIterableInterval) -> Vec< &syn ::Type >
  {
  if let syn ::Type ::Path(syn ::TypePath 
  {
   path: syn ::Path { ref segments, .. },
   ..
 }) = ty
  {
   let last = &segments.last();
   if last.is_none() 
   {
  return vec![ty];
 }
   let args = &last.unwrap().arguments;
   if let syn ::PathArguments ::AngleBracketed(ref args2) = args 
   {
  let args3 = &args2.args;
  let left = range.left().into_left_closed();
  let mut right = range.right().into_right_closed();
  let len = args3.len();
  if right == isize ::MAX 
  {
   right = len as isize;
 }
  // dbg!( left );
  // dbg!( right );
  // dbg!( len );
  let selected: Vec< &syn ::Type > = args3
   .iter()
   .skip_while(|e| !matches!(e, syn ::GenericArgument ::Type(_)))
   .skip(usize ::try_from(left.max(0)).unwrap())
   .take(usize ::try_from((right - left + 1).min(len as isize - left).max(0)).unwrap())
   .map(|e| {
  if let syn ::GenericArgument ::Type(ty) = e
  {
   ty
 } else {
   unreachable!("Expects Type")
 }
 })
   .collect();
  return selected;
 }
 }
  vec![ty]
 }

  /// Checks if a given [`syn ::Type`] is an `Option` type.
  ///
  /// This function examines a type to determine if it represents an `Option`.
  /// It is useful for scenarios where type-specific behavior needs to be conditional
  /// on whether the type is optional or not.
  ///
  /// # Example
  ///
  /// ```rust
  /// let type_string = "Option< i32 >";
  /// let parsed_type: syn ::Type = syn ::parse_str( type_string ).expect( "Type should parse correctly" );
  /// assert!( macro_tools ::typ ::is_optional( &parsed_type ) );
  /// ```
  ///
  #[ must_use ]
  pub fn is_optional(ty: &syn ::Type) -> bool
  {
  typ ::type_rightmost(ty) == Some("Option".to_string())
 }

  /// Extracts the first generic parameter from a given `syn ::Type` if any exists.
  ///
  /// This function is designed to analyze a type and retrieve its first generic parameter.
  /// It is particularly useful when working with complex types in macro expansions and needs
  /// to extract specific type information for further processing.
  ///
  ///
  /// # Example
  /// ```rust
  /// let type_string = "Result< Option< i32 >, Error >";
  /// let parsed_type: syn ::Type = syn ::parse_str( type_string ).expect( "Type should parse correctly" );
  /// let first_param = macro_tools ::typ ::parameter_first( &parsed_type ).expect( "Should have at least one parameter" );
  /// // Option< i32 >
  /// ```
  /// # Errors
  /// qqq: docs
  pub fn parameter_first(ty: &syn ::Type) -> Result< &syn ::Type >
  {
  typ ::type_parameters(ty, 0..=0)
   .first()
   .copied()
   .ok_or_else(|| syn_err!(ty, "Expects at least one parameter here: \n  {}", qt! { #ty }))
 }
}

#[ doc( inline ) ]
#[ allow( unused_imports ) ]
pub use own :: *;

/// Own namespace of the module.
#[ allow( unused_imports ) ]
pub mod own 
{

  use super :: *;
  #[ doc( inline ) ]
  pub use orphan :: *;
  #[ doc( inline ) ]
  pub use private :: { type_rightmost, type_parameters, is_optional, parameter_first };
}

/// Orphan namespace of the module.
#[ allow( unused_imports ) ]
pub mod orphan 
{

  use super :: *;
  #[ doc( inline ) ]
  pub use exposed :: *;
}

/// Exposed namespace of the module.
#[ allow( unused_imports ) ]
pub mod exposed 
{

  use super :: *;

  pub use super ::super ::typ;

  // pub use super ::own as typ;

  #[ doc( inline ) ]
  pub use prelude :: *;
}

/// Prelude to use essentials: `use my_module ::prelude :: *`.
#[ allow( unused_imports ) ]
pub mod prelude 
{
  use super :: *;
}