1+ use constants:: * ;
2+ use failure;
13use objects:: GqlObjectField ;
24use proc_macro2:: { Ident , Span , TokenStream } ;
35use query:: QueryContext ;
4- use selection:: Selection ;
6+ use selection:: { Selection , SelectionItem } ;
7+ use shared:: * ;
8+ use std:: borrow:: Cow ;
9+ use unions:: union_variants;
510
611#[ derive( Debug , PartialEq ) ]
712pub struct GqlInterface {
@@ -11,16 +16,81 @@ pub struct GqlInterface {
1116}
1217
1318impl GqlInterface {
19+ pub fn new ( name : Cow < str > ) -> GqlInterface {
20+ GqlInterface {
21+ name : name. into_owned ( ) ,
22+ implemented_by : Vec :: new ( ) ,
23+ fields : vec ! [ ] ,
24+ }
25+ }
26+
1427 pub fn response_for_selection (
1528 & self ,
16- _query_context : & QueryContext ,
17- _selection : & Selection ,
29+ query_context : & QueryContext ,
30+ selection : & Selection ,
1831 prefix : & str ,
19- ) -> TokenStream {
32+ ) -> Result < TokenStream , failure :: Error > {
2033 let name = Ident :: new ( & prefix, Span :: call_site ( ) ) ;
21- quote ! {
22- #[ derive( Debug , Deserialize ) ]
23- pub struct #name;
24- }
34+
35+ selection
36+ . extract_typename ( )
37+ . ok_or_else ( || format_err ! ( "Missing __typename in selection for {}" , prefix) ) ?;
38+
39+ let object_selection = Selection (
40+ selection. 0 . iter ( )
41+ // Only keep what we can handle
42+ . filter ( |f| match f {
43+ SelectionItem :: Field ( f) => f. name != "__typename" ,
44+ SelectionItem :: FragmentSpread ( _) => true ,
45+ SelectionItem :: InlineFragment ( _) => false ,
46+ } ) . map ( |a| ( * a) . clone ( ) ) . collect ( ) ,
47+ ) ;
48+
49+ let union_selection = Selection (
50+ selection. 0 . iter ( )
51+ // Only keep what we can handle
52+ . filter ( |f| match f {
53+ SelectionItem :: InlineFragment ( _) => true ,
54+ SelectionItem :: Field ( _) | SelectionItem :: FragmentSpread ( _) => false ,
55+ } ) . map ( |a| ( * a) . clone ( ) ) . collect ( ) ,
56+ ) ;
57+
58+ let object_fields =
59+ response_fields_for_selection ( & self . fields , query_context, & object_selection, prefix) ?;
60+
61+ let object_children =
62+ field_impls_for_selection ( & self . fields , query_context, & object_selection, prefix) ?;
63+ let ( union_variants, union_children) =
64+ union_variants ( & union_selection, query_context, prefix) ?;
65+
66+ let attached_enum_name = Ident :: new ( & format ! ( "{}On" , name) , Span :: call_site ( ) ) ;
67+ let ( attached_enum, last_object_field) = if union_variants. len ( ) > 0 {
68+ let attached_enum = quote ! {
69+ #[ derive( Deserialize , Debug , Serialize ) ]
70+ #[ serde( tag = "__typename" ) ]
71+ pub enum #attached_enum_name {
72+ #( #union_variants, ) *
73+ }
74+ } ;
75+ let last_object_field = quote ! ( #[ serde( flatten) ] on: #attached_enum_name, ) ;
76+ ( attached_enum, last_object_field)
77+ } else {
78+ ( quote ! ( ) , quote ! ( ) )
79+ } ;
80+
81+ Ok ( quote ! {
82+
83+ #( #object_children) *
84+
85+ #( #union_children) *
86+
87+ #attached_enum
88+
89+ #[ derive( Debug , Serialize , Deserialize ) ]
90+ pub struct #name {
91+ #( #object_fields, ) *
92+ #last_object_field
93+ }
94+ } )
2595 }
2696}
0 commit comments