use std::str::FromStr;
use crate::gqlgen::deprecation::DeprecationStrategy;
use crate::gqlgen::normalization::Normalization;
const DEPRECATION_ERROR: &str = "deprecated must be one of 'allow', 'deny', or 'warn'";
const NORMALIZATION_ERROR: &str = "normalization must be one of 'none' or 'rust'";
fn path_to_match() -> syn::Path {
syn::parse_str("graphql").expect("`graphql` is a valid path")
}
pub fn extract_attr(ast: &syn::DeriveInput, attr: &str) -> Result<String, syn::Error> {
let attributes = &ast.attrs;
let graphql_path = path_to_match();
let attribute = attributes
.iter()
.find(|attr| attr.path == graphql_path)
.ok_or_else(|| syn::Error::new_spanned(ast, "The graphql attribute is missing"))?;
if let syn::Meta::List(items) = &attribute.parse_meta().expect("Attribute is well formatted") {
for item in items.nested.iter() {
if let syn::NestedMeta::Meta(syn::Meta::NameValue(name_value)) = item {
let syn::MetaNameValue { path, lit, .. } = name_value;
if let Some(ident) = path.get_ident() {
if ident == attr {
if let syn::Lit::Str(lit) = lit {
return Ok(lit.value());
}
}
}
}
}
}
Err(syn::Error::new_spanned(
&ast,
format!("Attribute `{}` not found", attr),
))
}
pub fn extract_attr_list(ast: &syn::DeriveInput, attr: &str) -> Result<Vec<String>, syn::Error> {
let attributes = &ast.attrs;
let graphql_path = path_to_match();
let attribute = attributes
.iter()
.find(|attr| attr.path == graphql_path)
.ok_or_else(|| syn::Error::new_spanned(ast, "The graphql is missing"))?;
if let syn::Meta::List(items) = &attribute.parse_meta().expect("Attribute is well formatted") {
for item in items.nested.iter() {
if let syn::NestedMeta::Meta(syn::Meta::List(value_list)) = item {
if let Some(ident) = value_list.path.get_ident() {
if ident == attr {
return value_list
.nested
.iter()
.map(|lit| {
if let syn::NestedMeta::Lit(syn::Lit::Str(lit)) = lit {
Ok(lit.value())
} else {
Err(syn::Error::new_spanned(
lit,
"Attribute inside value list must be a literal",
))
}
})
.collect();
}
}
}
}
}
Err(syn::Error::new_spanned(ast, "Attribute not found"))
}
pub fn extract_deprecation_strategy(
ast: &syn::DeriveInput,
) -> Result<DeprecationStrategy, syn::Error> {
extract_attr(ast, "deprecated")?
.to_lowercase()
.as_str()
.parse()
.map_err(|_| syn::Error::new_spanned(ast, DEPRECATION_ERROR.to_owned()))
}
pub fn extract_normalization(ast: &syn::DeriveInput) -> Result<Normalization, syn::Error> {
extract_attr(ast, "normalization")?
.to_lowercase()
.as_str()
.parse()
.map_err(|_| syn::Error::new_spanned(ast, NORMALIZATION_ERROR))
}
pub fn extract_fragments_other_variant(ast: &syn::DeriveInput) -> bool {
extract_attr(ast, "fragments_other_variant")
.ok()
.and_then(|s| FromStr::from_str(s.as_str()).ok())
.unwrap_or(false)
}