Impl reflect
traits for enums
This commit is contained in:
parent
505e25cea2
commit
48631e9b25
12 changed files with 111 additions and 17 deletions
|
@ -10,6 +10,8 @@ use syn::{
|
|||
parse_quote,
|
||||
};
|
||||
|
||||
use crate::util::span_container::SpanContainer;
|
||||
|
||||
/// [`Behaviour`] parametrization of the code generation.
|
||||
///
|
||||
/// [`Behaviour`]: juniper::behavior
|
||||
|
@ -55,3 +57,9 @@ impl Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<SpanContainer<Self>>> for Type {
|
||||
fn from(attr: Option<SpanContainer<Self>>) -> Self {
|
||||
attr.map(SpanContainer::into_inner).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -494,7 +494,7 @@ impl OnMethod {
|
|||
ty: argument.ty.as_ref().clone(),
|
||||
description: attr.description.as_ref().map(|d| d.as_ref().value()),
|
||||
default: attr.default.as_ref().map(|v| v.as_ref().clone()),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ pub(crate) fn expand(input: TokenStream) -> syn::Result<TokenStream> {
|
|||
description,
|
||||
context,
|
||||
scalar,
|
||||
behavior: attr.behavior.into(),
|
||||
values,
|
||||
has_ignored_variants,
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@ use syn::{
|
|||
|
||||
use crate::{
|
||||
common::{
|
||||
behavior,
|
||||
parse::{
|
||||
attr::{err, OptionExt as _},
|
||||
ParseBufferExt as _,
|
||||
|
@ -71,6 +72,17 @@ struct ContainerAttr {
|
|||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||
scalar: Option<SpanContainer<scalar::AttrValue>>,
|
||||
|
||||
/// Explicitly specified type of the custom [`Behavior`] to parametrize this
|
||||
/// [GraphQL enum][0] implementation with.
|
||||
///
|
||||
/// If [`None`], then [`behavior::Standard`] will be used for the generated
|
||||
/// code.
|
||||
///
|
||||
/// [`Behavior`]: juniper::behavior
|
||||
/// [`behavior::Standard`]: juniper::behavior::Standard
|
||||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||
behavior: Option<SpanContainer<behavior::Type>>,
|
||||
|
||||
/// Explicitly specified [`RenameRule`] for all [values][1] of this
|
||||
/// [GraphQL enum][0].
|
||||
///
|
||||
|
@ -128,6 +140,13 @@ impl Parse for ContainerAttr {
|
|||
.replace(SpanContainer::new(ident.span(), Some(scl.span()), scl))
|
||||
.none_or_else(|_| err::dup_arg(&ident))?
|
||||
}
|
||||
"behave" | "behavior" => {
|
||||
input.parse::<token::Eq>()?;
|
||||
let bh = input.parse::<behavior::Type>()?;
|
||||
out.behavior
|
||||
.replace(SpanContainer::new(ident.span(), Some(bh.span()), bh))
|
||||
.none_or_else(|_| err::dup_arg(&ident))?
|
||||
}
|
||||
"rename_all" => {
|
||||
input.parse::<token::Eq>()?;
|
||||
let val = input.parse::<syn::LitStr>()?;
|
||||
|
@ -161,6 +180,7 @@ impl ContainerAttr {
|
|||
description: try_merge_opt!(description: self, another),
|
||||
context: try_merge_opt!(context: self, another),
|
||||
scalar: try_merge_opt!(scalar: self, another),
|
||||
behavior: try_merge_opt!(behavior: self, another),
|
||||
rename_values: try_merge_opt!(rename_values: self, another),
|
||||
is_internal: self.is_internal || another.is_internal,
|
||||
})
|
||||
|
@ -389,6 +409,13 @@ struct Definition {
|
|||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||
scalar: scalar::Type,
|
||||
|
||||
/// [`Behavior`] parametrization to generate code with for this
|
||||
/// [GraphQL enum][0].
|
||||
///
|
||||
/// [`Behavior`]: juniper::behavior
|
||||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||
behavior: behavior::Type,
|
||||
|
||||
/// [Values][1] of this [GraphQL enum][0].
|
||||
///
|
||||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||
|
@ -411,6 +438,8 @@ impl ToTokens for Definition {
|
|||
self.impl_from_input_value_tokens().to_tokens(into);
|
||||
self.impl_to_input_value_tokens().to_tokens(into);
|
||||
self.impl_reflection_traits_tokens().to_tokens(into);
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
self.impl_reflect().to_tokens(into);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -729,6 +758,47 @@ impl Definition {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns generated code implementing [`reflect::BaseType`],
|
||||
/// [`reflect::BaseSubTypes`] and [`reflect::WrappedType`] traits for this
|
||||
/// [GraphQL enum][0].
|
||||
///
|
||||
/// [`reflect::BaseSubTypes`]: juniper::reflect::BaseSubTypes
|
||||
/// [`reflect::BaseType`]: juniper::reflect::BaseType
|
||||
/// [`reflect::WrappedType`]: juniper::reflect::WrappedType
|
||||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||
fn impl_reflect(&self) -> TokenStream {
|
||||
let bh = &self.behavior;
|
||||
let (ty, generics) = self.ty_and_generics();
|
||||
let (impl_gens, _, where_clause) = generics.split_for_impl();
|
||||
|
||||
let name = &self.name;
|
||||
|
||||
quote! {
|
||||
#[automatically_derived]
|
||||
impl#impl_gens ::juniper::reflect::BaseType<#bh> for #ty
|
||||
#where_clause
|
||||
{
|
||||
const NAME: ::juniper::reflect::Type = #name;
|
||||
}
|
||||
|
||||
#[automatically_derived]
|
||||
impl#impl_gens ::juniper::reflect::BaseSubTypes<#bh> for #ty
|
||||
#where_clause
|
||||
{
|
||||
const NAMES: ::juniper::reflect::Types =
|
||||
&[<Self as ::juniper::reflect::BaseType<#bh>>::NAME];
|
||||
}
|
||||
|
||||
#[automatically_derived]
|
||||
impl#impl_gens ::juniper::reflect::WrappedType<#bh> for #ty
|
||||
#where_clause
|
||||
{
|
||||
const VALUE: ::juniper::reflect::WrappedValue =
|
||||
::juniper::reflect::wrap::SINGULAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns prepared [`syn::Generics`] for [`GraphQLType`] trait (and
|
||||
/// similar) implementation of this enum.
|
||||
///
|
||||
|
@ -787,4 +857,19 @@ impl Definition {
|
|||
|
||||
generics
|
||||
}
|
||||
|
||||
/// Returns prepared self [`syn::Type`] and [`syn::Generics`] for a trait
|
||||
/// implementation.
|
||||
#[must_use]
|
||||
fn ty_and_generics(&self) -> (syn::Type, syn::Generics) {
|
||||
let generics = self.generics.clone();
|
||||
|
||||
let ty = {
|
||||
let ident = &self.ident;
|
||||
let (_, ty_gen, _) = generics.split_for_impl();
|
||||
parse_quote! { #ident#ty_gen }
|
||||
};
|
||||
|
||||
(ty, generics)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ fn expand_on_trait(
|
|||
description: attr.description.map(|d| d.into_inner().into_boxed_str()),
|
||||
context,
|
||||
scalar,
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
fields,
|
||||
implemented_for: attr
|
||||
.implemented_for
|
||||
|
@ -218,7 +218,7 @@ fn parse_trait_method(
|
|||
description,
|
||||
deprecated,
|
||||
ident: method_ident.clone(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
arguments: Some(arguments),
|
||||
has_receiver: method.sig.receiver().is_some(),
|
||||
is_async: method.sig.asyncness.is_some(),
|
||||
|
@ -313,7 +313,7 @@ fn expand_on_derive_input(
|
|||
description: attr.description.map(|d| d.into_inner().into_boxed_str()),
|
||||
context,
|
||||
scalar,
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
fields,
|
||||
implemented_for: attr
|
||||
.implemented_for
|
||||
|
@ -388,7 +388,7 @@ fn parse_struct_field(field: &mut syn::Field, renaming: &RenameRule) -> Option<f
|
|||
description,
|
||||
deprecated,
|
||||
ident: field_ident.clone(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
arguments: None,
|
||||
has_receiver: false,
|
||||
is_async: false,
|
||||
|
|
|
@ -97,7 +97,7 @@ pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
|
|||
description: attr.description.map(|d| d.into_inner().into_boxed_str()),
|
||||
context,
|
||||
scalar,
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
fields,
|
||||
implemented_for: attr
|
||||
.implemented_for
|
||||
|
@ -160,7 +160,7 @@ fn parse_field(field: &syn::Field, renaming: &RenameRule) -> Option<field::Defin
|
|||
description,
|
||||
deprecated,
|
||||
ident: field_ident.clone(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
arguments: None,
|
||||
has_receiver: false,
|
||||
is_async: false,
|
||||
|
|
|
@ -121,7 +121,7 @@ where
|
|||
description: attr.description.map(SpanContainer::into_inner),
|
||||
context,
|
||||
scalar,
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
fields,
|
||||
interfaces: attr
|
||||
.interfaces
|
||||
|
@ -229,7 +229,7 @@ fn parse_field(
|
|||
description,
|
||||
deprecated,
|
||||
ident: method_ident.clone(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
arguments: Some(arguments),
|
||||
has_receiver: method.sig.receiver().is_some(),
|
||||
is_async: method.sig.asyncness.is_some(),
|
||||
|
|
|
@ -98,7 +98,7 @@ fn expand_struct(ast: syn::DeriveInput) -> syn::Result<Definition<Query>> {
|
|||
.map(SpanContainer::into_inner)
|
||||
.unwrap_or_else(|| parse_quote! { () }),
|
||||
scalar,
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
fields,
|
||||
interfaces: attr
|
||||
.interfaces
|
||||
|
@ -154,7 +154,7 @@ fn parse_field(field: &syn::Field, renaming: &RenameRule) -> Option<field::Defin
|
|||
description,
|
||||
deprecated,
|
||||
ident: field_ident.clone(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
arguments: None,
|
||||
has_receiver: false,
|
||||
is_async: false,
|
||||
|
|
|
@ -74,7 +74,7 @@ pub(crate) struct Attr {
|
|||
pub(crate) scalar: Option<SpanContainer<scalar::AttrValue>>,
|
||||
|
||||
/// Explicitly specified type of the custom [`Behavior`] to parametrize this
|
||||
/// [GraphQL object][0] type implementation with.
|
||||
/// [GraphQL object][0] implementation with.
|
||||
///
|
||||
/// If [`None`], then [`behavior::Standard`] will be used for the generated
|
||||
/// code.
|
||||
|
|
|
@ -64,7 +64,7 @@ fn expand_on_type_alias(
|
|||
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
||||
scalar,
|
||||
scalar_value: attr.scalar.as_deref().into(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
|
@ -99,7 +99,7 @@ fn expand_on_derive_input(
|
|||
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
||||
scalar,
|
||||
scalar_value: attr.scalar.as_deref().into(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
|
|
|
@ -38,7 +38,7 @@ pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
|
|||
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
||||
scalar,
|
||||
scalar_value: attr.scalar.as_deref().into(),
|
||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
||||
behavior: attr.behavior.into(),
|
||||
}
|
||||
.to_token_stream())
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ struct Attr {
|
|||
scalar: Option<SpanContainer<scalar::AttrValue>>,
|
||||
|
||||
/// Explicitly specified type of the custom [`Behavior`] to parametrize this
|
||||
/// [GraphQL scalar][0] type implementation with.
|
||||
/// [GraphQL scalar][0] implementation with.
|
||||
///
|
||||
/// If [`None`], then [`behavior::Standard`] will be used for the generated
|
||||
/// code.
|
||||
|
@ -1721,7 +1721,7 @@ impl ParseToken {
|
|||
#[derive(Debug, Default)]
|
||||
struct FieldAttr {
|
||||
/// Explicitly specified type of the custom [`Behavior`] used for
|
||||
/// [GraphQL scalar][0] implementation by the [`Field`].
|
||||
/// [GraphQL scalar][0] implementation by this [`Field`].
|
||||
///
|
||||
/// If [`None`], then [`behavior::Standard`] will be used for the generated
|
||||
/// code.
|
||||
|
|
Loading…
Reference in a new issue