#![allow(unused)]
use proc_macro2::Span;
use syn::{
parse::Parser, punctuated::Punctuated, Attribute, Fields, Ident, ItemEnum, ItemStruct,
MetaList, Path, Result, Token, Type,
};
pub(crate) fn has_derive(meta_list: &MetaList) -> bool {
let ident = Ident::new("derive", Span::call_site());
meta_list.path.segments.iter().any(|p| p.ident == ident)
}
pub(crate) fn check_if_unit(item_enum: &ItemEnum) -> Result<()> {
for variant in item_enum.variants.iter() {
match &variant.fields {
Fields::Unit => {
}
_ => {
return Err(syn::Error::new_spanned(
variant,
"Only unit fields are allowed (with no tuple and struct variants)",
));
}
}
}
Ok(())
}
pub(crate) fn check_if_state(item_struct: &ItemStruct) -> bool {
let borderless = Ident::new("borderless", Span::call_site());
let target = Ident::new("State", Span::call_site());
for attr in item_struct.attrs.iter() {
let meta_list = match &attr.meta {
syn::Meta::List(m) => m,
_ => continue,
};
if !has_derive(meta_list) {
continue;
}
let parser = Punctuated::<Path, Token![,]>::parse_separated_nonempty;
let derive_paths = parser.parse2(meta_list.tokens.clone()).unwrap_or_default();
for path in derive_paths {
let mut iter = path.segments.iter();
let first = iter.next();
let sec = iter.next();
match (first, sec) {
(Some(first), Some(sec)) => {
if first.ident == borderless || sec.ident == target {
return true;
}
}
(Some(first), None) => {
if first.ident == target {
return true;
}
}
_ => {}
}
}
}
false
}
pub(crate) fn check_if_action(attr: &Attribute) -> bool {
check_attr_name(attr, "action")
}
pub(crate) fn check_if_schedule(attr: &Attribute) -> bool {
check_attr_name(attr, "schedule")
}
pub(crate) fn check_if_background_task(attr: &Attribute) -> bool {
check_attr_name(attr, "background_task")
}
pub(crate) fn check_if_http_handler(attr: &Attribute) -> bool {
check_attr_name(attr, "http_handler")
}
fn check_attr_name(attr: &Attribute, attr_name: &'static str) -> bool {
let target_attr = Ident::new(attr_name, Span::call_site());
if let Some(ident) = attr.path().get_ident() {
if *ident != target_attr {
return false;
}
} else {
let borderless = Ident::new("borderless", Span::call_site());
let mut iter = attr.path().segments.iter();
let first = iter.next();
let sec = iter.next();
match (first, sec) {
(Some(first), Some(sec)) => {
if first.ident != borderless || sec.ident != target_attr {
return false;
}
}
_ => {
return false;
}
}
};
true
}