1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! xxx : update documentation of file

/// Internal namespace.
pub( crate ) mod private
{
  use super::super::*;

  /// Ensures the last field in a struct has a trailing comma.
  ///
  /// This function checks and modifies the fields of a given struct, `input`, ensuring that the last field, whether in
  /// named or unnamed structs, ends with a trailing comma. This adjustment is commonly needed in macro-generated
  /// code to maintain consistency and syntactical correctness across different struct types, including unit structs
  /// which are unaffected as they do not contain fields.
  ///
  /// # Arguments
  ///
  /// * `input` - A reference to the struct (`syn::ItemStruct`) whose fields are to be checked and modified.
  ///
  /// # Returns
  ///
  /// Returns a modified clone of the input struct (`syn::ItemStruct`) where the last field in named or unnamed
  /// structs has a trailing comma. Unit structs remain unchanged as they do not contain fields.
  ///
  /// # Examples
  ///
  /// ```
  /// use macro_tools::
  /// {
  ///   syn::{ parse_quote, ItemStruct },
  ///   quote::quote,
  /// };
  ///
  /// // Create a struct using `parse_quote!` macro
  /// let input_struct : ItemStruct = parse_quote!
  /// {
  ///   struct Example
  ///   {
  ///     field1 : i32,
  ///     field2 : String
  ///   }
  /// };
  ///
  /// // Apply `ensure_comma` to ensure the last field has a trailing comma
  /// let modified_struct = macro_tools::item::ensure_comma( &input_struct );
  ///
  /// // Now `modified_struct` will have a trailing comma after `field2`
  /// assert_eq!( quote!( #modified_struct ).to_string(), quote!
  /// {
  ///   struct Example
  ///   {
  ///     field1 : i32,
  ///     field2 : String,
  ///   }
  /// }.to_string() );
  /// ```

  pub fn ensure_comma( input : &syn::ItemStruct ) -> syn::ItemStruct
  {
    let mut new_input = input.clone(); // Clone the input to modify it

    match &mut new_input.fields
    {
      // Handle named fields
      syn::Fields::Named( syn::FieldsNamed { named, .. } ) =>
      {
        punctuated::ensure_trailing_comma( named )
      },
      // Handle unnamed fields (tuples)
      syn::Fields::Unnamed( syn::FieldsUnnamed { unnamed, .. } ) =>
      {
        punctuated::ensure_trailing_comma( unnamed )
      },
      // Do nothing for unit structs
      syn::Fields::Unit => {}
    }

    new_input
  }

}

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

/// Protected namespace of the module.
pub mod protected
{
  #[ doc( inline ) ]
  #[ allow( unused_imports ) ]
  pub use super::orphan::*;
  #[ doc( inline ) ]
  #[ allow( unused_imports ) ]
  pub use super::private::
  {
    ensure_comma,
  };
}

// xxx : external attr instead of internal?
/// Orphan namespace of the module.
pub mod orphan
{
  #[ doc( inline ) ]
  #[ allow( unused_imports ) ]
  pub use super::exposed::*;
  #[ doc( inline ) ]
  #[ allow( unused_imports ) ]
  pub use super::private::
  {
  };
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::protected as item;
  #[ doc( inline ) ]
  #[ allow( unused_imports ) ]
  pub use super::
  {
    prelude::*,
  };
}

/// Prelude to use essentials: `use my_module::prelude::*`.
pub mod prelude
{
}