use proc_macro2::{TokenTree, Ident, Span, TokenStream};
use quote::quote;
use syn::{
spanned::Spanned, Attribute, Data, Fields, Field, GenericArgument, Meta, PathArguments, Type
};
use crate::derives::TableField;
pub fn get_table_list(data: Data) -> Vec<TableField> {
let mut table_list: Vec<TableField> = vec![];
match data {
Data::Struct(data_struct) => {
match data_struct.fields {
Fields::Named(fields) => {
for field in fields.named {
let name = get_field_name(&field);
let mut field_type = format!("");
let mut exist = true;
let mut _option = false;
field.attrs.iter()
.filter(| attr | attr.path().is_ident("table_field"))
.for_each(|attr| {
if let Meta::List(lits) = &attr.meta {
let mut table_field_content = format!("");
let _ = &lits.tokens.clone().into_iter().for_each(| ts | {
table_field_content += &ts.span().source_text().unwrap_or(format!(""));
});
table_field_content = table_field_content.replace(" ", "");
let exist_vec: &Vec<&str> = &table_field_content.split(',').collect();
if exist_vec.contains(&"exist=false") {
exist = false;
}
}
});
if let Type::Path(_ty) = &field.ty {
_ty.path.segments.iter().for_each(|ps| {
if let Some(_o) = &ps.span().source_text() {
if _o == &"Option".to_string() {
_option = true;
} else {
field_type = ps.ident.to_string();
_option = false;
return;
}
if let PathArguments::AngleBracketed(_abga) = &ps.arguments {
_abga.args.iter().for_each(|b| {
if let GenericArgument::Type(path) = &b {
if let Type::Path(_path) = &path {
if let Some(text) = _path.span().source_text() {
field_type = text;
};
}
}
})
}
}
});
}
table_list.push( TableField {
name,
field_type,
exist,
_option
})
}
},
_ => ()
}
},
_ => ()
}
table_list
}
fn get_field_name(field: &Field) -> String {
if let Some(ident) = &field.ident {
if let Some(text) = ident.span().source_text() {
return text;
}
}
format!("")
}
pub fn get_table_name(attrs: Vec<Attribute>) -> String {
let mut table_name = format!("");
attrs
.iter()
.filter(|attr| attr.path().is_ident("mydb"))
.into_iter()
.for_each(| attr | {
if let Meta::List(lits) = &attr.meta {
let _ = &lits.tokens.clone().into_iter().for_each(| ts | {
if let TokenTree::Literal(l_name) = ts {
if l_name.to_string().len() > 0 {
table_name = l_name.to_string().replace('"', "");
} else {
eprintln!("no setting table_name")
}
}
});
}
});
table_name
}
pub fn set_ident(name: &String) -> Ident {
Ident::new(&name, Span::call_site())
}
pub fn type_value(_option: bool, field_type: &String) -> TokenStream {
if _option {
if field_type == "DateTime" {
quote! { Option<DateTime<Utc>> }
} else {
let f_type = set_ident(field_type);
quote! { Option<#f_type> }
}
} else {
if field_type == "DateTime" {
quote! { DateTime<Utc> }
} else {
let f_type = set_ident(field_type);
quote! { #f_type }
}
}
}