From b1be8f1d29cdfb640ef1bfd4e205ac4a7798382f Mon Sep 17 00:00:00 2001
From: tyranron <tyranron@gmail.com>
Date: Mon, 30 May 2022 19:09:15 +0200
Subject: [PATCH] Improve codegen for scalars, vol.2

---
 juniper/src/lib.rs                        |  1 +
 juniper/src/reflect/mod.rs                |  1 +
 juniper/src/types/scalars.rs              | 12 ---
 juniper/src/types/str.rs                  | 18 ++++-
 juniper_codegen/src/graphql_scalar/mod.rs | 93 ++++++++++++++++++-----
 5 files changed, 90 insertions(+), 35 deletions(-)
 create mode 100644 juniper/src/reflect/mod.rs

diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs
index 6e35d230..9340608a 100644
--- a/juniper/src/lib.rs
+++ b/juniper/src/lib.rs
@@ -36,6 +36,7 @@ pub mod http;
 pub mod integrations;
 mod introspection;
 pub mod parser;
+pub mod reflect;
 pub mod resolve;
 pub(crate) mod schema;
 mod types;
diff --git a/juniper/src/reflect/mod.rs b/juniper/src/reflect/mod.rs
new file mode 100644
index 00000000..e91f009a
--- /dev/null
+++ b/juniper/src/reflect/mod.rs
@@ -0,0 +1 @@
+pub use crate::macros::reflect::*;
diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs
index 66e26e74..ac781770 100644
--- a/juniper/src/types/scalars.rs
+++ b/juniper/src/types/scalars.rs
@@ -196,18 +196,6 @@ where
     })
 }
 
-impl<S> reflect::WrappedType<S> for str {
-    const VALUE: reflect::WrappedValue = 1;
-}
-
-impl<S> reflect::BaseType<S> for str {
-    const NAME: reflect::Type = "String";
-}
-
-impl<S> reflect::BaseSubTypes<S> for str {
-    const NAMES: reflect::Types = &[<Self as reflect::BaseType<S>>::NAME];
-}
-
 impl<S> GraphQLType<S> for str
 where
     S: ScalarValue,
diff --git a/juniper/src/types/str.rs b/juniper/src/types/str.rs
index af7c966c..24861e6b 100644
--- a/juniper/src/types/str.rs
+++ b/juniper/src/types/str.rs
@@ -7,7 +7,7 @@ use std::{rc::Rc, sync::Arc};
 use futures::future;
 
 use crate::{
-    graphql,
+    graphql, reflect,
     meta::MetaType,
     parser::{ParseError, ScalarToken},
     resolve, BoxFuture, ExecutionResult, Executor, Registry, ScalarValue, Selection,
@@ -25,8 +25,8 @@ impl<Info: ?Sized, S: ScalarValue> resolve::Type<Info, S> for str {
 }
 
 impl<Info: ?Sized> resolve::TypeName<Info> for str {
-    fn type_name(info: &Info) -> &str {
-        <String as resolve::TypeName<Info>>::type_name(info)
+    fn type_name(_: &Info) -> &'static str {
+        <Self as reflect::BaseType<()>>::NAME
     }
 }
 
@@ -119,3 +119,15 @@ impl<S> graphql::OutputType<S> for str {
 impl<S> graphql::Scalar<S> for str {
     fn assert_scalar() {}
 }
+
+impl<S> reflect::BaseType<S> for str {
+    const NAME: reflect::Type = <String as reflect::BaseType<S>>::NAME;
+}
+
+impl<S> reflect::BaseSubTypes<S> for str {
+    const NAMES: reflect::Types = &[<Self as reflect::BaseType<S>>::NAME];
+}
+
+impl<S> reflect::WrappedType<S> for str {
+    const VALUE: reflect::WrappedValue = 1;
+}
diff --git a/juniper_codegen/src/graphql_scalar/mod.rs b/juniper_codegen/src/graphql_scalar/mod.rs
index 45a34291..7e98eae3 100644
--- a/juniper_codegen/src/graphql_scalar/mod.rs
+++ b/juniper_codegen/src/graphql_scalar/mod.rs
@@ -329,12 +329,14 @@ impl ToTokens for Definition {
         self.impl_to_input_value_tokens().to_tokens(into);
         self.impl_from_input_value_tokens().to_tokens(into);
         self.impl_parse_scalar_value_tokens().to_tokens(into);
-        self.impl_reflection_traits_tokens().to_tokens(into);
         ////////////////////////////////////////////////////////////////////////
-        self.impl_resolve_type_name().to_tokens(into);
         self.impl_resolve_type().to_tokens(into);
+        self.impl_resolve_type_name().to_tokens(into);
         self.impl_resolve_input_value().to_tokens(into);
         self.impl_resolve_scalar_token().to_tokens(into);
+        self.impl_input_and_output_type().to_tokens(into);
+        //self.impl_scalar().to_tokens(into);
+        self.impl_reflect().to_tokens(into);
     }
 }
 
@@ -363,6 +365,56 @@ impl Definition {
         }
     }
 
+    /// Returns generated code implementing [`graphql::InputType`] and
+    /// [`graphql::OutputType`] traits for this [GraphQL scalar][0].
+    ///
+    /// [`graphql::InputType`]: juniper::graphql::InputType
+    /// [`graphql::OutputType`]: juniper::graphql::OutputType
+    /// [0]: https://spec.graphql.org/October2021#sec-Scalars
+    #[must_use]
+    fn impl_input_and_output_type(&self) -> TokenStream {
+        let (ty, generics) = self.ty_and_generics();
+        let (scalar, generics) = self.mix_scalar(generics);
+        let (impl_gens, _, where_clause) = generics.split_for_impl();
+
+        quote! {
+            #[automatically_derived]
+            impl#impl_gens ::juniper::graphql::InputType<#scalar> for #ty
+                #where_clause
+            {
+                fn assert_input_type() {}
+            }
+
+            #[automatically_derived]
+            impl#impl_gens ::juniper::graphql::OutputType<#scalar> for #ty
+                #where_clause
+            {
+                fn assert_output_type() {}
+            }
+        }
+    }
+
+    /// Returns generated code implementing [`graphql::Scalar`] trait for this
+    /// [GraphQL scalar][0].
+    ///
+    /// [`graphql::Scalar`]: juniper::graphql::Scalar
+    /// [0]: https://spec.graphql.org/October2021#sec-Scalars
+    #[must_use]
+    fn impl_scalar(&self) -> TokenStream {
+        let (ty, generics) = self.ty_and_generics();
+        let (scalar, generics) = self.mix_scalar(generics);
+        let (impl_gens, _, where_clause) = generics.split_for_impl();
+
+        quote! {
+            #[automatically_derived]
+            impl#impl_gens ::juniper::graphql::Scalar<#scalar> for #ty
+                #where_clause
+            {
+                fn assert_scalar() {}
+            }
+        }
+    }
+
     /// Returns generated code implementing [`GraphQLType`] trait for this
     /// [GraphQL scalar][1].
     ///
@@ -696,41 +748,42 @@ impl Definition {
         }
     }
 
-    /// Returns generated code implementing [`BaseType`], [`BaseSubTypes`] and
-    /// [`WrappedType`] traits for this [GraphQL scalar][1].
+    /// Returns generated code implementing [`reflect::BaseType`],
+    /// [`reflect::BaseSubTypes`] and [`reflect::WrappedType`] traits for this
+    /// [GraphQL scalar][0].
     ///
-    /// [`BaseSubTypes`]: juniper::macros::reflection::BaseSubTypes
-    /// [`BaseType`]: juniper::macros::reflection::BaseType
-    /// [`WrappedType`]: juniper::macros::reflection::WrappedType
-    /// [1]: https://spec.graphql.org/October2021#sec-Scalars
-    fn impl_reflection_traits_tokens(&self) -> TokenStream {
-        let scalar = &self.scalar;
-        let name = &self.name;
-
-        let (ty, generics) = self.impl_self_and_generics(false);
+    /// [`reflect::BaseSubTypes`]: juniper::reflection::BaseSubTypes
+    /// [`reflect::BaseType`]: juniper::reflection::BaseType
+    /// [`reflect::WrappedType`]: juniper::reflection::WrappedType
+    /// [0]: https://spec.graphql.org/October2021#sec-Scalars
+    fn impl_reflect(&self) -> TokenStream {
+        let (ty, generics) = self.ty_and_generics();
+        let (scalar, generics) = self.mix_scalar(generics);
         let (impl_gens, _, where_clause) = generics.split_for_impl();
 
+        let name = &self.name;
+
         quote! {
             #[automatically_derived]
-            impl#impl_gens ::juniper::macros::reflect::BaseType<#scalar> for #ty
+            impl#impl_gens ::juniper::reflect::BaseType<#scalar> for #ty
                 #where_clause
             {
-                const NAME: ::juniper::macros::reflect::Type = #name;
+                const NAME: ::juniper::reflect::Type = #name;
             }
 
             #[automatically_derived]
-            impl#impl_gens ::juniper::macros::reflect::BaseSubTypes<#scalar> for #ty
+            impl#impl_gens ::juniper::reflect::BaseSubTypes<#scalar> for #ty
                 #where_clause
             {
-                const NAMES: ::juniper::macros::reflect::Types =
-                    &[<Self as ::juniper::macros::reflect::BaseType<#scalar>>::NAME];
+                const NAMES: ::juniper::reflect::Types =
+                    &[<Self as ::juniper::reflect::BaseType<#scalar>>::NAME];
             }
 
             #[automatically_derived]
-            impl#impl_gens ::juniper::macros::reflect::WrappedType<#scalar> for #ty
+            impl#impl_gens ::juniper::reflect::WrappedType<#scalar> for #ty
                 #where_clause
             {
-                const VALUE: ::juniper::macros::reflect::WrappedValue = 1;
+                const VALUE: ::juniper::reflect::WrappedValue = 1;
             }
         }
     }