ast.rs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. use crate::{attr, ty_ext::*, AttrsContainer, Ctxt};
  2. use syn::{self, punctuated::Punctuated};
  3. pub struct ASTContainer<'a> {
  4. /// The struct or enum name (without generics).
  5. pub ident: syn::Ident,
  6. /// Attributes on the structure.
  7. pub attrs: AttrsContainer,
  8. /// The contents of the struct or enum.
  9. pub data: ASTData<'a>,
  10. }
  11. impl<'a> ASTContainer<'a> {
  12. pub fn from_ast(cx: &Ctxt, ast: &'a syn::DeriveInput) -> Option<ASTContainer<'a>> {
  13. let attrs = AttrsContainer::from_ast(cx, ast);
  14. // syn::DeriveInput
  15. // 1. syn::DataUnion
  16. // 2. syn::DataStruct
  17. // 3. syn::DataEnum
  18. let data = match &ast.data {
  19. syn::Data::Struct(data) => {
  20. // https://docs.rs/syn/1.0.48/syn/struct.DataStruct.html
  21. let (style, fields) = struct_from_ast(cx, &data.fields);
  22. ASTData::Struct(style, fields)
  23. },
  24. syn::Data::Union(_) => {
  25. cx.error_spanned_by(ast, "Does not support derive for unions");
  26. return None;
  27. },
  28. syn::Data::Enum(data) => {
  29. // https://docs.rs/syn/1.0.48/syn/struct.DataEnum.html
  30. ASTData::Enum(enum_from_ast(cx, &ast.ident, &data.variants, &ast.attrs))
  31. },
  32. };
  33. let ident = ast.ident.clone();
  34. let item = ASTContainer { ident, attrs, data };
  35. Some(item)
  36. }
  37. }
  38. pub enum ASTData<'a> {
  39. Struct(ASTStyle, Vec<ASTField<'a>>),
  40. Enum(Vec<ASTEnumVariant<'a>>),
  41. }
  42. impl<'a> ASTData<'a> {
  43. pub fn all_fields(&'a self) -> Box<dyn Iterator<Item = &'a ASTField<'a>> + 'a> {
  44. match self {
  45. ASTData::Enum(variants) => Box::new(variants.iter().flat_map(|variant| variant.fields.iter())),
  46. ASTData::Struct(_, fields) => Box::new(fields.iter()),
  47. }
  48. }
  49. pub fn all_variants(&'a self) -> Box<dyn Iterator<Item = &'a attr::ASTEnumAttrVariant> + 'a> {
  50. match self {
  51. ASTData::Enum(variants) => {
  52. let iter = variants.iter().map(|variant| &variant.attrs);
  53. Box::new(iter)
  54. },
  55. ASTData::Struct(_, fields) => {
  56. let iter = fields.iter().flat_map(|_| None);
  57. Box::new(iter)
  58. },
  59. }
  60. }
  61. pub fn all_idents(&'a self) -> Box<dyn Iterator<Item = &'a syn::Ident> + 'a> {
  62. match self {
  63. ASTData::Enum(variants) => Box::new(variants.iter().map(|v| &v.ident)),
  64. ASTData::Struct(_, fields) => {
  65. let iter = fields.iter().flat_map(|f| match &f.member {
  66. syn::Member::Named(ident) => Some(ident),
  67. _ => None,
  68. });
  69. Box::new(iter)
  70. },
  71. }
  72. }
  73. }
  74. /// A variant of an enum.
  75. pub struct ASTEnumVariant<'a> {
  76. pub ident: syn::Ident,
  77. pub attrs: attr::ASTEnumAttrVariant,
  78. pub style: ASTStyle,
  79. pub fields: Vec<ASTField<'a>>,
  80. pub original: &'a syn::Variant,
  81. }
  82. impl<'a> ASTEnumVariant<'a> {
  83. pub fn name(&self) -> String { self.ident.to_string() }
  84. }
  85. pub enum BracketCategory {
  86. Other,
  87. Opt,
  88. Vec,
  89. Map((String, String)),
  90. }
  91. pub struct ASTField<'a> {
  92. pub member: syn::Member,
  93. pub attrs: attr::ASTAttrField,
  94. pub ty: &'a syn::Type,
  95. pub original: &'a syn::Field,
  96. pub bracket_ty: Option<syn::Ident>,
  97. pub bracket_inner_ty: Option<syn::Ident>,
  98. pub bracket_category: Option<BracketCategory>,
  99. }
  100. impl<'a> ASTField<'a> {
  101. pub fn new(cx: &Ctxt, field: &'a syn::Field, index: usize) -> Self {
  102. let mut bracket_inner_ty = None;
  103. let mut bracket_ty = None;
  104. let mut bracket_category = Some(BracketCategory::Other);
  105. match parse_ty(cx, &field.ty) {
  106. Ok(Some(inner)) => {
  107. match inner.primitive_ty {
  108. PrimitiveTy::Map(map_info) => {
  109. bracket_category = Some(BracketCategory::Map((map_info.key.clone(), map_info.value)))
  110. },
  111. PrimitiveTy::Vec => {
  112. bracket_category = Some(BracketCategory::Vec);
  113. },
  114. PrimitiveTy::Opt => {
  115. bracket_category = Some(BracketCategory::Opt);
  116. },
  117. PrimitiveTy::Other => {
  118. bracket_category = Some(BracketCategory::Other);
  119. },
  120. }
  121. match *inner.bracket_ty_info {
  122. Some(bracketed_inner_ty) => {
  123. bracket_inner_ty = Some(bracketed_inner_ty.ident.clone());
  124. bracket_ty = Some(inner.ident.clone());
  125. },
  126. None => {
  127. bracket_ty = Some(inner.ident.clone());
  128. },
  129. }
  130. },
  131. Ok(None) => {
  132. cx.error_spanned_by(&field.ty, "fail to get the ty inner type");
  133. },
  134. Err(e) => {
  135. eprintln!("ASTField parser failed: {:?} with error: {}", field, e);
  136. panic!()
  137. },
  138. }
  139. ASTField {
  140. member: match &field.ident {
  141. Some(ident) => syn::Member::Named(ident.clone()),
  142. None => syn::Member::Unnamed(index.into()),
  143. },
  144. attrs: attr::ASTAttrField::from_ast(cx, index, field),
  145. ty: &field.ty,
  146. original: field,
  147. bracket_ty,
  148. bracket_inner_ty,
  149. bracket_category,
  150. }
  151. }
  152. pub fn ty_as_str(&self) -> String {
  153. match self.bracket_inner_ty {
  154. Some(ref ty) => ty.to_string(),
  155. None => self.bracket_ty.as_ref().unwrap().clone().to_string(),
  156. }
  157. }
  158. #[allow(dead_code)]
  159. pub fn name(&self) -> Option<syn::Ident> {
  160. if let syn::Member::Named(ident) = &self.member {
  161. Some(ident.clone())
  162. } else {
  163. None
  164. }
  165. }
  166. pub fn is_option(&self) -> bool { attr::is_option(&self.ty) }
  167. }
  168. #[derive(Copy, Clone)]
  169. pub enum ASTStyle {
  170. Struct,
  171. /// Many unnamed fields.
  172. Tuple,
  173. /// One unnamed field.
  174. NewType,
  175. /// No fields.
  176. Unit,
  177. }
  178. pub fn struct_from_ast<'a>(cx: &Ctxt, fields: &'a syn::Fields) -> (ASTStyle, Vec<ASTField<'a>>) {
  179. match fields {
  180. syn::Fields::Named(fields) => (ASTStyle::Struct, fields_from_ast(cx, &fields.named)),
  181. syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
  182. (ASTStyle::NewType, fields_from_ast(cx, &fields.unnamed))
  183. },
  184. syn::Fields::Unnamed(fields) => (ASTStyle::Tuple, fields_from_ast(cx, &fields.unnamed)),
  185. syn::Fields::Unit => (ASTStyle::Unit, Vec::new()),
  186. }
  187. }
  188. pub fn enum_from_ast<'a>(
  189. cx: &Ctxt,
  190. ident: &syn::Ident,
  191. variants: &'a Punctuated<syn::Variant, Token![,]>,
  192. enum_attrs: &[syn::Attribute],
  193. ) -> Vec<ASTEnumVariant<'a>> {
  194. variants
  195. .iter()
  196. .flat_map(|variant| {
  197. let attrs = attr::ASTEnumAttrVariant::from_ast(cx, ident, variant, enum_attrs);
  198. let (style, fields) = struct_from_ast(cx, &variant.fields);
  199. Some(ASTEnumVariant {
  200. ident: variant.ident.clone(),
  201. attrs,
  202. style,
  203. fields,
  204. original: variant,
  205. })
  206. })
  207. .collect()
  208. }
  209. fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a Punctuated<syn::Field, Token![,]>) -> Vec<ASTField<'a>> {
  210. fields
  211. .iter()
  212. .enumerate()
  213. .map(|(index, field)| ASTField::new(cx, field, index))
  214. .collect()
  215. }