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,
|
parse_quote,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::util::span_container::SpanContainer;
|
||||||
|
|
||||||
/// [`Behaviour`] parametrization of the code generation.
|
/// [`Behaviour`] parametrization of the code generation.
|
||||||
///
|
///
|
||||||
/// [`Behaviour`]: juniper::behavior
|
/// [`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(),
|
ty: argument.ty.as_ref().clone(),
|
||||||
description: attr.description.as_ref().map(|d| d.as_ref().value()),
|
description: attr.description.as_ref().map(|d| d.as_ref().value()),
|
||||||
default: attr.default.as_ref().map(|v| v.as_ref().clone()),
|
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,
|
description,
|
||||||
context,
|
context,
|
||||||
scalar,
|
scalar,
|
||||||
|
behavior: attr.behavior.into(),
|
||||||
values,
|
values,
|
||||||
has_ignored_variants,
|
has_ignored_variants,
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@ use syn::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{
|
common::{
|
||||||
|
behavior,
|
||||||
parse::{
|
parse::{
|
||||||
attr::{err, OptionExt as _},
|
attr::{err, OptionExt as _},
|
||||||
ParseBufferExt as _,
|
ParseBufferExt as _,
|
||||||
|
@ -71,6 +72,17 @@ struct ContainerAttr {
|
||||||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||||
scalar: Option<SpanContainer<scalar::AttrValue>>,
|
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
|
/// Explicitly specified [`RenameRule`] for all [values][1] of this
|
||||||
/// [GraphQL enum][0].
|
/// [GraphQL enum][0].
|
||||||
///
|
///
|
||||||
|
@ -128,6 +140,13 @@ impl Parse for ContainerAttr {
|
||||||
.replace(SpanContainer::new(ident.span(), Some(scl.span()), scl))
|
.replace(SpanContainer::new(ident.span(), Some(scl.span()), scl))
|
||||||
.none_or_else(|_| err::dup_arg(&ident))?
|
.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" => {
|
"rename_all" => {
|
||||||
input.parse::<token::Eq>()?;
|
input.parse::<token::Eq>()?;
|
||||||
let val = input.parse::<syn::LitStr>()?;
|
let val = input.parse::<syn::LitStr>()?;
|
||||||
|
@ -161,6 +180,7 @@ impl ContainerAttr {
|
||||||
description: try_merge_opt!(description: self, another),
|
description: try_merge_opt!(description: self, another),
|
||||||
context: try_merge_opt!(context: self, another),
|
context: try_merge_opt!(context: self, another),
|
||||||
scalar: try_merge_opt!(scalar: 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),
|
rename_values: try_merge_opt!(rename_values: self, another),
|
||||||
is_internal: self.is_internal || another.is_internal,
|
is_internal: self.is_internal || another.is_internal,
|
||||||
})
|
})
|
||||||
|
@ -389,6 +409,13 @@ struct Definition {
|
||||||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
||||||
scalar: scalar::Type,
|
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].
|
/// [Values][1] of this [GraphQL enum][0].
|
||||||
///
|
///
|
||||||
/// [0]: https://spec.graphql.org/October2021#sec-Enums
|
/// [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_from_input_value_tokens().to_tokens(into);
|
||||||
self.impl_to_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_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
|
/// Returns prepared [`syn::Generics`] for [`GraphQLType`] trait (and
|
||||||
/// similar) implementation of this enum.
|
/// similar) implementation of this enum.
|
||||||
///
|
///
|
||||||
|
@ -787,4 +857,19 @@ impl Definition {
|
||||||
|
|
||||||
generics
|
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()),
|
description: attr.description.map(|d| d.into_inner().into_boxed_str()),
|
||||||
context,
|
context,
|
||||||
scalar,
|
scalar,
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
fields,
|
fields,
|
||||||
implemented_for: attr
|
implemented_for: attr
|
||||||
.implemented_for
|
.implemented_for
|
||||||
|
@ -218,7 +218,7 @@ fn parse_trait_method(
|
||||||
description,
|
description,
|
||||||
deprecated,
|
deprecated,
|
||||||
ident: method_ident.clone(),
|
ident: method_ident.clone(),
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
arguments: Some(arguments),
|
arguments: Some(arguments),
|
||||||
has_receiver: method.sig.receiver().is_some(),
|
has_receiver: method.sig.receiver().is_some(),
|
||||||
is_async: method.sig.asyncness.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()),
|
description: attr.description.map(|d| d.into_inner().into_boxed_str()),
|
||||||
context,
|
context,
|
||||||
scalar,
|
scalar,
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
fields,
|
fields,
|
||||||
implemented_for: attr
|
implemented_for: attr
|
||||||
.implemented_for
|
.implemented_for
|
||||||
|
@ -388,7 +388,7 @@ fn parse_struct_field(field: &mut syn::Field, renaming: &RenameRule) -> Option<f
|
||||||
description,
|
description,
|
||||||
deprecated,
|
deprecated,
|
||||||
ident: field_ident.clone(),
|
ident: field_ident.clone(),
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
arguments: None,
|
arguments: None,
|
||||||
has_receiver: false,
|
has_receiver: false,
|
||||||
is_async: 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()),
|
description: attr.description.map(|d| d.into_inner().into_boxed_str()),
|
||||||
context,
|
context,
|
||||||
scalar,
|
scalar,
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
fields,
|
fields,
|
||||||
implemented_for: attr
|
implemented_for: attr
|
||||||
.implemented_for
|
.implemented_for
|
||||||
|
@ -160,7 +160,7 @@ fn parse_field(field: &syn::Field, renaming: &RenameRule) -> Option<field::Defin
|
||||||
description,
|
description,
|
||||||
deprecated,
|
deprecated,
|
||||||
ident: field_ident.clone(),
|
ident: field_ident.clone(),
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
arguments: None,
|
arguments: None,
|
||||||
has_receiver: false,
|
has_receiver: false,
|
||||||
is_async: false,
|
is_async: false,
|
||||||
|
|
|
@ -121,7 +121,7 @@ where
|
||||||
description: attr.description.map(SpanContainer::into_inner),
|
description: attr.description.map(SpanContainer::into_inner),
|
||||||
context,
|
context,
|
||||||
scalar,
|
scalar,
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
fields,
|
fields,
|
||||||
interfaces: attr
|
interfaces: attr
|
||||||
.interfaces
|
.interfaces
|
||||||
|
@ -229,7 +229,7 @@ fn parse_field(
|
||||||
description,
|
description,
|
||||||
deprecated,
|
deprecated,
|
||||||
ident: method_ident.clone(),
|
ident: method_ident.clone(),
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
arguments: Some(arguments),
|
arguments: Some(arguments),
|
||||||
has_receiver: method.sig.receiver().is_some(),
|
has_receiver: method.sig.receiver().is_some(),
|
||||||
is_async: method.sig.asyncness.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)
|
.map(SpanContainer::into_inner)
|
||||||
.unwrap_or_else(|| parse_quote! { () }),
|
.unwrap_or_else(|| parse_quote! { () }),
|
||||||
scalar,
|
scalar,
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
fields,
|
fields,
|
||||||
interfaces: attr
|
interfaces: attr
|
||||||
.interfaces
|
.interfaces
|
||||||
|
@ -154,7 +154,7 @@ fn parse_field(field: &syn::Field, renaming: &RenameRule) -> Option<field::Defin
|
||||||
description,
|
description,
|
||||||
deprecated,
|
deprecated,
|
||||||
ident: field_ident.clone(),
|
ident: field_ident.clone(),
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
arguments: None,
|
arguments: None,
|
||||||
has_receiver: false,
|
has_receiver: false,
|
||||||
is_async: false,
|
is_async: false,
|
||||||
|
|
|
@ -74,7 +74,7 @@ pub(crate) struct Attr {
|
||||||
pub(crate) scalar: Option<SpanContainer<scalar::AttrValue>>,
|
pub(crate) scalar: Option<SpanContainer<scalar::AttrValue>>,
|
||||||
|
|
||||||
/// Explicitly specified type of the custom [`Behavior`] to parametrize this
|
/// 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
|
/// If [`None`], then [`behavior::Standard`] will be used for the generated
|
||||||
/// code.
|
/// code.
|
||||||
|
|
|
@ -64,7 +64,7 @@ fn expand_on_type_alias(
|
||||||
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
||||||
scalar,
|
scalar,
|
||||||
scalar_value: attr.scalar.as_deref().into(),
|
scalar_value: attr.scalar.as_deref().into(),
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
|
@ -99,7 +99,7 @@ fn expand_on_derive_input(
|
||||||
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
||||||
scalar,
|
scalar,
|
||||||
scalar_value: attr.scalar.as_deref().into(),
|
scalar_value: attr.scalar.as_deref().into(),
|
||||||
behavior: attr.behavior.map(|bh| bh.into_inner()).unwrap_or_default(),
|
behavior: attr.behavior.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
|
||||||
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
specified_by_url: attr.specified_by_url.as_deref().cloned(),
|
||||||
scalar,
|
scalar,
|
||||||
scalar_value: attr.scalar.as_deref().into(),
|
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())
|
.to_token_stream())
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct Attr {
|
||||||
scalar: Option<SpanContainer<scalar::AttrValue>>,
|
scalar: Option<SpanContainer<scalar::AttrValue>>,
|
||||||
|
|
||||||
/// Explicitly specified type of the custom [`Behavior`] to parametrize this
|
/// 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
|
/// If [`None`], then [`behavior::Standard`] will be used for the generated
|
||||||
/// code.
|
/// code.
|
||||||
|
@ -1721,7 +1721,7 @@ impl ParseToken {
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct FieldAttr {
|
struct FieldAttr {
|
||||||
/// Explicitly specified type of the custom [`Behavior`] used for
|
/// 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
|
/// If [`None`], then [`behavior::Standard`] will be used for the generated
|
||||||
/// code.
|
/// code.
|
||||||
|
|
Loading…
Reference in a new issue