ast.rs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #![allow(clippy::all)]
  2. #![allow(unused_attributes)]
  3. #![allow(unused_assignments)]
  4. use crate::event_attrs::EventEnumAttrs;
  5. use crate::node_attrs::NodeStructAttrs;
  6. use crate::{
  7. is_recognizable_field, ty_ext::*, ASTResult, PBAttrsContainer, PBStructAttrs, NODE_TYPE,
  8. };
  9. use proc_macro2::Ident;
  10. use syn::Meta::NameValue;
  11. use syn::{self, punctuated::Punctuated};
  12. pub struct ASTContainer<'a> {
  13. /// The struct or enum name (without generics).
  14. pub ident: syn::Ident,
  15. pub node_type: Option<String>,
  16. /// Attributes on the structure.
  17. pub pb_attrs: PBAttrsContainer,
  18. /// The contents of the struct or enum.
  19. pub data: ASTData<'a>,
  20. }
  21. impl<'a> ASTContainer<'a> {
  22. pub fn from_ast(ast_result: &ASTResult, ast: &'a syn::DeriveInput) -> Option<ASTContainer<'a>> {
  23. let attrs = PBAttrsContainer::from_ast(ast_result, ast);
  24. // syn::DeriveInput
  25. // 1. syn::DataUnion
  26. // 2. syn::DataStruct
  27. // 3. syn::DataEnum
  28. let data = match &ast.data {
  29. syn::Data::Struct(data) => {
  30. // https://docs.rs/syn/1.0.48/syn/struct.DataStruct.html
  31. let (style, fields) = struct_from_ast(ast_result, &data.fields);
  32. ASTData::Struct(style, fields)
  33. },
  34. syn::Data::Union(_) => {
  35. ast_result.error_spanned_by(ast, "Does not support derive for unions");
  36. return None;
  37. },
  38. syn::Data::Enum(data) => {
  39. // https://docs.rs/syn/1.0.48/syn/struct.DataEnum.html
  40. ASTData::Enum(enum_from_ast(
  41. ast_result,
  42. &ast.ident,
  43. &data.variants,
  44. &ast.attrs,
  45. ))
  46. },
  47. };
  48. let ident = ast.ident.clone();
  49. let node_type = get_node_type(ast_result, &ident, &ast.attrs);
  50. let item = ASTContainer {
  51. ident,
  52. pb_attrs: attrs,
  53. node_type,
  54. data,
  55. };
  56. Some(item)
  57. }
  58. }
  59. pub enum ASTData<'a> {
  60. Struct(ASTStyle, Vec<ASTField<'a>>),
  61. Enum(Vec<ASTEnumVariant<'a>>),
  62. }
  63. impl<'a> ASTData<'a> {
  64. pub fn all_fields(&'a self) -> Box<dyn Iterator<Item = &'a ASTField<'a>> + 'a> {
  65. match self {
  66. ASTData::Enum(variants) => {
  67. Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
  68. },
  69. ASTData::Struct(_, fields) => Box::new(fields.iter()),
  70. }
  71. }
  72. pub fn all_variants(&'a self) -> Box<dyn Iterator<Item = &'a EventEnumAttrs> + 'a> {
  73. match self {
  74. ASTData::Enum(variants) => {
  75. let iter = variants.iter().map(|variant| &variant.attrs);
  76. Box::new(iter)
  77. },
  78. ASTData::Struct(_, fields) => {
  79. let iter = fields.iter().flat_map(|_| None);
  80. Box::new(iter)
  81. },
  82. }
  83. }
  84. pub fn all_idents(&'a self) -> Box<dyn Iterator<Item = &'a syn::Ident> + 'a> {
  85. match self {
  86. ASTData::Enum(variants) => Box::new(variants.iter().map(|v| &v.ident)),
  87. ASTData::Struct(_, fields) => {
  88. let iter = fields.iter().flat_map(|f| match &f.member {
  89. syn::Member::Named(ident) => Some(ident),
  90. _ => None,
  91. });
  92. Box::new(iter)
  93. },
  94. }
  95. }
  96. }
  97. /// A variant of an enum.
  98. pub struct ASTEnumVariant<'a> {
  99. pub ident: syn::Ident,
  100. pub attrs: EventEnumAttrs,
  101. pub style: ASTStyle,
  102. pub fields: Vec<ASTField<'a>>,
  103. pub original: &'a syn::Variant,
  104. }
  105. impl<'a> ASTEnumVariant<'a> {
  106. pub fn name(&self) -> String {
  107. self.ident.to_string()
  108. }
  109. }
  110. pub enum BracketCategory {
  111. Other,
  112. Opt,
  113. Vec,
  114. Map((String, String)),
  115. }
  116. pub struct ASTField<'a> {
  117. pub member: syn::Member,
  118. pub pb_attrs: PBStructAttrs,
  119. pub node_attrs: NodeStructAttrs,
  120. pub ty: &'a syn::Type,
  121. pub original: &'a syn::Field,
  122. // If the field is Vec<String>, then the bracket_ty will be Vec
  123. pub bracket_ty: Option<syn::Ident>,
  124. // If the field is Vec<String>, then the bracket_inner_ty will be String
  125. pub bracket_inner_ty: Option<syn::Ident>,
  126. pub bracket_category: Option<BracketCategory>,
  127. }
  128. impl<'a> ASTField<'a> {
  129. pub fn new(cx: &ASTResult, field: &'a syn::Field, index: usize) -> Result<Self, String> {
  130. let mut bracket_inner_ty = None;
  131. let mut bracket_ty = None;
  132. let mut bracket_category = Some(BracketCategory::Other);
  133. match parse_ty(cx, &field.ty) {
  134. Ok(Some(inner)) => {
  135. match inner.primitive_ty {
  136. PrimitiveTy::Map(map_info) => {
  137. bracket_category = Some(BracketCategory::Map((map_info.key.clone(), map_info.value)))
  138. },
  139. PrimitiveTy::Vec => {
  140. bracket_category = Some(BracketCategory::Vec);
  141. },
  142. PrimitiveTy::Opt => {
  143. bracket_category = Some(BracketCategory::Opt);
  144. },
  145. PrimitiveTy::Other => {
  146. bracket_category = Some(BracketCategory::Other);
  147. },
  148. }
  149. match *inner.bracket_ty_info {
  150. Some(bracketed_inner_ty) => {
  151. bracket_inner_ty = Some(bracketed_inner_ty.ident.clone());
  152. bracket_ty = Some(inner.ident.clone());
  153. },
  154. None => {
  155. bracket_ty = Some(inner.ident.clone());
  156. },
  157. }
  158. },
  159. Ok(None) => {
  160. let msg = format!("Fail to get the ty inner type: {:?}", field);
  161. return Err(msg);
  162. },
  163. Err(e) => {
  164. eprintln!("ASTField parser failed: {:?} with error: {}", field, e);
  165. return Err(e);
  166. },
  167. }
  168. Ok(ASTField {
  169. member: match &field.ident {
  170. Some(ident) => syn::Member::Named(ident.clone()),
  171. None => syn::Member::Unnamed(index.into()),
  172. },
  173. pb_attrs: PBStructAttrs::from_ast(cx, index, field),
  174. node_attrs: NodeStructAttrs::from_ast(cx, index, field),
  175. ty: &field.ty,
  176. original: field,
  177. bracket_ty,
  178. bracket_inner_ty,
  179. bracket_category,
  180. })
  181. }
  182. pub fn ty_as_str(&self) -> String {
  183. match self.bracket_inner_ty {
  184. Some(ref ty) => ty.to_string(),
  185. None => self.bracket_ty.as_ref().unwrap().clone().to_string(),
  186. }
  187. }
  188. pub fn name(&self) -> Option<syn::Ident> {
  189. if let syn::Member::Named(ident) = &self.member {
  190. Some(ident.clone())
  191. } else {
  192. None
  193. }
  194. }
  195. }
  196. #[derive(Copy, Clone)]
  197. pub enum ASTStyle {
  198. Struct,
  199. /// Many unnamed fields.
  200. Tuple,
  201. /// One unnamed field.
  202. NewType,
  203. /// No fields.
  204. Unit,
  205. }
  206. pub fn struct_from_ast<'a>(
  207. cx: &ASTResult,
  208. fields: &'a syn::Fields,
  209. ) -> (ASTStyle, Vec<ASTField<'a>>) {
  210. match fields {
  211. syn::Fields::Named(fields) => (ASTStyle::Struct, fields_from_ast(cx, &fields.named)),
  212. syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
  213. (ASTStyle::NewType, fields_from_ast(cx, &fields.unnamed))
  214. },
  215. syn::Fields::Unnamed(fields) => (ASTStyle::Tuple, fields_from_ast(cx, &fields.unnamed)),
  216. syn::Fields::Unit => (ASTStyle::Unit, Vec::new()),
  217. }
  218. }
  219. pub fn enum_from_ast<'a>(
  220. cx: &ASTResult,
  221. ident: &syn::Ident,
  222. variants: &'a Punctuated<syn::Variant, Token![,]>,
  223. enum_attrs: &[syn::Attribute],
  224. ) -> Vec<ASTEnumVariant<'a>> {
  225. variants
  226. .iter()
  227. .flat_map(|variant| {
  228. let attrs = EventEnumAttrs::from_ast(cx, ident, variant, enum_attrs);
  229. let (style, fields) = struct_from_ast(cx, &variant.fields);
  230. Some(ASTEnumVariant {
  231. ident: variant.ident.clone(),
  232. attrs,
  233. style,
  234. fields,
  235. original: variant,
  236. })
  237. })
  238. .collect()
  239. }
  240. fn fields_from_ast<'a>(
  241. cx: &ASTResult,
  242. fields: &'a Punctuated<syn::Field, Token![,]>,
  243. ) -> Vec<ASTField<'a>> {
  244. fields
  245. .iter()
  246. .enumerate()
  247. .flat_map(|(index, field)| {
  248. if is_recognizable_field(field) {
  249. ASTField::new(cx, field, index).ok()
  250. } else {
  251. None
  252. }
  253. })
  254. .collect()
  255. }
  256. fn get_node_type(
  257. ast_result: &ASTResult,
  258. struct_name: &Ident,
  259. attrs: &[syn::Attribute],
  260. ) -> Option<String> {
  261. let mut node_type = None;
  262. attrs
  263. .iter()
  264. .filter(|attr| attr.path.segments.iter().any(|s| s.ident == NODE_TYPE))
  265. .for_each(|attr| {
  266. if let Ok(NameValue(named_value)) = attr.parse_meta() {
  267. if node_type.is_some() {
  268. ast_result.error_spanned_by(struct_name, "Duplicate node type definition");
  269. }
  270. if let syn::Lit::Str(s) = named_value.lit {
  271. node_type = Some(s.value());
  272. }
  273. }
  274. });
  275. node_type
  276. }