use super::Conversion;
use crate::parse::util::{Attributes, SqlSafeName};
use deluxe::{ExtractAttributes, HasAttributes, ParseAttributes, ParseMetaItem, Result};
use quote::ToTokens;
use syn::{Expr, Ident, Type};
#[derive(ExtractAttributes)]
#[deluxe(attributes(alias))]
pub struct Alias(#[deluxe(flatten)] pub Vec<Ident>);
pub struct ActuallyExists<'t, T: HasAttributes, A: ParseAttributes<'t, T>> {
pub exists: bool,
pub span: proc_macro2::Span,
_marker: core::marker::PhantomData<fn() -> &'t (A, T)>,
}
impl<'t, T: HasAttributes, A: ParseAttributes<'t, T>> ParseAttributes<'t, T>
for ActuallyExists<'t, T, A>
{
fn path_matches(path: &syn::Path) -> bool {
A::path_matches(path)
}
fn parse_attributes(obj: &'t T) -> Result<Self> {
if let Some(next) = ::deluxe::____private::parse_helpers::ref_tokens::<A, _>(obj).next() {
Ok(Self {
exists: true,
span: next.2,
_marker: core::marker::PhantomData,
})
} else {
Ok(Self {
exists: false,
span: proc_macro2::Span::call_site(),
_marker: core::marker::PhantomData,
})
}
}
}
pub trait AttributeFlag: Sized {
fn path() -> &'static str;
}
pub struct Flag<A: AttributeFlag> {
pub set: bool,
pub span: proc_macro2::Span,
_marker: core::marker::PhantomData<fn() -> A>,
}
impl<A: AttributeFlag> Flag<A> {
fn new(set: bool, span: proc_macro2::Span) -> Self {
Self {
set,
span,
_marker: core::marker::PhantomData,
}
}
}
impl<T: HasAttributes, A: AttributeFlag> ExtractAttributes<T> for Flag<A> {
fn path_matches(path: &syn::Path) -> bool {
deluxe::____private::parse_helpers::path_matches(path, &[A::path()])
}
fn extract_attributes(obj: &mut T) -> Result<Self> {
let tokens = ::deluxe::____private::parse_helpers::take_tokens::<Self, _>(obj)?;
let mut count = 0;
let mut values = quote::quote! {};
let mut span = None;
for (value, _key, s) in tokens {
count += 1;
span = Some(s);
value.to_tokens(&mut values);
}
if count == 0 {
Ok(Self::new(false, proc_macro2::Span::call_site()))
} else if count == 1 && values.is_empty() {
Ok(Self::new(true, span.unwrap()))
} else if !values.is_empty() {
Err(syn::Error::new(
span.unwrap(),
format!("#[{}] doesn't allow any extra fields", A::path()),
))
} else {
Err(syn::Error::new(
span.unwrap(),
format!("#[{}] should only be specified once", A::path()),
))
}
}
}
pub struct IdField;
impl AttributeFlag for IdField {
fn path() -> &'static str {
"id"
}
}
pub struct StaticField;
impl AttributeFlag for StaticField {
fn path() -> &'static str {
"static_field"
}
}
pub struct Indexed;
impl AttributeFlag for Indexed {
fn path() -> &'static str {
"indexed"
}
}
pub struct Entity;
impl AttributeFlag for Entity {
fn path() -> &'static str {
"entity"
}
}
pub struct Event;
impl AttributeFlag for Event {
fn path() -> &'static str {
"event"
}
}
#[derive(Clone, Debug, ExtractAttributes, ParseAttributes)]
#[deluxe(attributes(sql))]
pub struct TransformerFieldSqlParseConfig {
#[deluxe(alias = rename)]
pub name: Option<SqlSafeName>,
#[deluxe(with = deluxe::with::maybe_quoted, alias = type)]
pub ty: Option<Expr>,
pub nullable: deluxe::Flag,
}
#[derive(Debug, Clone, ExtractAttributes, ParseAttributes)]
#[deluxe(attributes(db))]
pub struct TransformerFieldDbParseConfig {
#[deluxe(with = deluxe::with::maybe_quoted, alias = rename)]
pub name: Option<Ident>,
#[deluxe(alias = type)]
pub ty: Option<Type>,
#[deluxe(default)]
pub db_to_field: Conversion,
#[deluxe(default)]
pub field_to_db: Conversion,
}
#[derive(Debug, Default, Clone, ExtractAttributes, ParseAttributes)]
#[deluxe(attributes(gql))]
pub struct TransformerFieldGraphqlParseConfig {
#[deluxe(with = deluxe::with::maybe_quoted, alias = rename)]
pub name: Option<Ident>,
#[deluxe(default)]
pub attrs: Attributes,
#[deluxe(with = deluxe::with::maybe_quoted)]
pub complexity: Option<Expr>,
pub hidden: deluxe::Flag,
#[deluxe(default)]
pub input: TransformerFieldGraphqlParseInputConfig,
#[deluxe(default)]
pub output: TransformerFieldGraphqlParseOutputConfig,
}
#[derive(Debug, Default, Clone, ParseMetaItem)]
pub(super) struct TransformerFieldGraphqlParseInputConfig {
#[deluxe(alias = type)]
pub ty: Option<Type>,
#[deluxe(default)]
pub gql_to_field: Conversion,
}
#[derive(Debug, Default, Clone, ParseMetaItem)]
pub(super) struct TransformerFieldGraphqlParseOutputConfig {
#[deluxe(alias = type)]
pub ty: Option<Type>,
#[deluxe(default)]
pub field_to_gql: Conversion,
}
#[derive(Debug, Clone, ExtractAttributes, ParseAttributes)]
#[deluxe(attributes(derived_from))]
pub struct DerivedField {
#[deluxe(with = deluxe::with::maybe_quoted)]
pub field: Ident,
#[deluxe(with = deluxe::with::maybe_quoted)]
pub complexity: Option<Expr>,
pub multiple: deluxe::Flag,
}