From fa03c7fa4d1884a700e17c13aa55cada2b0ad20e Mon Sep 17 00:00:00 2001
From: tyranron <tyranron@gmail.com>
Date: Mon, 27 Jun 2022 17:05:01 +0200
Subject: [PATCH] Impl `graphql::Enum` trait for enums [skip ci]

---
 juniper/src/graphql/mod.rs              | 15 +++-
 juniper_codegen/src/graphql_enum/mod.rs | 93 ++++++++++++++++++++++++-
 2 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/juniper/src/graphql/mod.rs b/juniper/src/graphql/mod.rs
index a88b154d..097e775d 100644
--- a/juniper/src/graphql/mod.rs
+++ b/juniper/src/graphql/mod.rs
@@ -6,9 +6,22 @@ pub use crate::{
     macros::{input_value, value, vars},
     resolve::Type,
     value::Value,
-    GraphQLScalar as Scalar,
+    GraphQLEnum as Enum, GraphQLScalar as Scalar,
 };
 
+pub trait Enum<
+    'inp,
+    TypeInfo: ?Sized,
+    Context: ?Sized,
+    ScalarValue: 'inp,
+    Behavior: ?Sized = behavior::Standard,
+>:
+    InputType<'inp, TypeInfo, ScalarValue, Behavior>
+    + OutputType<TypeInfo, Context, ScalarValue, Behavior>
+{
+    fn assert_enum();
+}
+
 /*
 pub trait Interface<S>: OutputType<S>
    + resolve::TypeName
diff --git a/juniper_codegen/src/graphql_enum/mod.rs b/juniper_codegen/src/graphql_enum/mod.rs
index 7cb9a558..ae1b2322 100644
--- a/juniper_codegen/src/graphql_enum/mod.rs
+++ b/juniper_codegen/src/graphql_enum/mod.rs
@@ -445,9 +445,9 @@ impl ToTokens for Definition {
         self.impl_resolve_value_async().to_tokens(into);
         self.impl_resolve_to_input_value().to_tokens(into);
         self.impl_resolve_input_value().to_tokens(into);
-        //self.impl_graphql_input_type().to_tokens(into);
-        //self.impl_graphql_output_type().to_tokens(into);
-        //self.impl_graphql_enum().to_tokens(into);
+        self.impl_graphql_input_type().to_tokens(into);
+        self.impl_graphql_output_type().to_tokens(into);
+        self.impl_graphql_enum().to_tokens(into);
         self.impl_reflect().to_tokens(into);
     }
 }
@@ -479,6 +479,93 @@ impl Definition {
         }
     }
 
+    /// Returns generated code implementing [`graphql::InputType`] trait for
+    /// this [GraphQL enum][0].
+    ///
+    /// [`graphql::InputType`]: juniper::graphql::InputType
+    /// [0]: https://spec.graphql.org/October2021#sec-Enums
+    #[must_use]
+    fn impl_graphql_input_type(&self) -> TokenStream {
+        let bh = &self.behavior;
+        let (ty, generics) = self.ty_and_generics();
+        let (inf, generics) = self.mix_type_info(generics);
+        let (sv, generics) = self.mix_scalar_value(generics);
+        let (lt, mut generics) = self.mix_input_lifetime(generics, &sv);
+        generics.make_where_clause().predicates.push(parse_quote! {
+            Self: ::juniper::resolve::Type<#inf, #sv, #bh>
+                  + ::juniper::resolve::ToInputValue<#sv, #bh>
+                  + ::juniper::resolve::InputValue<#lt, #sv, #bh>
+        });
+        let (impl_gens, _, where_clause) = generics.split_for_impl();
+
+        quote! {
+            #[automatically_derived]
+            impl#impl_gens ::juniper::graphql::InputType<#lt, #inf, #sv, #bh>
+                for #ty #where_clause
+            {
+                fn assert_input_type() {}
+            }
+        }
+    }
+
+    /// Returns generated code implementing [`graphql::OutputType`] trait for
+    /// this [GraphQL enum][0].
+    ///
+    /// [`graphql::OutputType`]: juniper::graphql::OutputType
+    /// [0]: https://spec.graphql.org/October2021#sec-Enums
+    #[must_use]
+    fn impl_graphql_output_type(&self) -> TokenStream {
+        let bh = &self.behavior;
+        let (ty, generics) = self.ty_and_generics();
+        let (inf, generics) = self.mix_type_info(generics);
+        let (cx, generics) = self.mix_context(generics);
+        let (sv, mut generics) = self.mix_scalar_value(generics);
+        generics.make_where_clause().predicates.push(parse_quote! {
+            Self: ::juniper::resolve::Type<#inf, #sv, #bh>
+                  + ::juniper::resolve::Value<#inf, #cx, #sv, #bh>
+                  + ::juniper::resolve::ValueAsync<#inf, #cx, #sv, #bh>
+        });
+        let (impl_gens, _, where_clause) = generics.split_for_impl();
+
+        quote! {
+            #[automatically_derived]
+            impl#impl_gens ::juniper::graphql::OutputType<#inf, #cx, #sv, #bh>
+                for #ty #where_clause
+            {
+                fn assert_output_type() {}
+            }
+        }
+    }
+
+    /// Returns generated code implementing [`graphql::Enum`] trait for this
+    /// [GraphQL enum][0].
+    ///
+    /// [`graphql::Enum`]: juniper::graphql::Enum
+    /// [0]: https://spec.graphql.org/October2021#sec-Enums
+    #[must_use]
+    fn impl_graphql_enum(&self) -> TokenStream {
+        let bh = &self.behavior;
+        let (ty, generics) = self.ty_and_generics();
+        let (inf, generics) = self.mix_type_info(generics);
+        let (cx, generics) = self.mix_context(generics);
+        let (sv, generics) = self.mix_scalar_value(generics);
+        let (lt, mut generics) = self.mix_input_lifetime(generics, &sv);
+        generics.make_where_clause().predicates.push(parse_quote! {
+            Self: ::juniper::graphql::InputType<#lt, #inf, #sv, #bh>
+                  + ::juniper::graphql::OutputType<#inf, #cx, #sv, #bh>
+        });
+        let (impl_gens, _, where_clause) = generics.split_for_impl();
+
+        quote! {
+            #[automatically_derived]
+            impl#impl_gens ::juniper::graphql::Enum<#lt, #inf, #cx, #sv, #bh>
+                for #ty #where_clause
+            {
+                fn assert_enum() {}
+            }
+        }
+    }
+
     /// Returns generated code implementing [`GraphQLType`] trait for this
     /// [GraphQL enum][0].
     ///