1
+ use constants:: * ;
2
+ use failure;
1
3
use objects:: GqlObjectField ;
2
4
use proc_macro2:: { Ident , Span , TokenStream } ;
3
5
use query:: QueryContext ;
4
- use selection:: Selection ;
6
+ use selection:: { Selection , SelectionItem } ;
7
+ use shared:: * ;
8
+ use std:: borrow:: Cow ;
9
+ use unions:: union_variants;
5
10
6
11
#[ derive( Debug , PartialEq ) ]
7
12
pub struct GqlInterface {
@@ -11,16 +16,81 @@ pub struct GqlInterface {
11
16
}
12
17
13
18
impl 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
+
14
27
pub fn response_for_selection (
15
28
& self ,
16
- _query_context : & QueryContext ,
17
- _selection : & Selection ,
29
+ query_context : & QueryContext ,
30
+ selection : & Selection ,
18
31
prefix : & str ,
19
- ) -> TokenStream {
32
+ ) -> Result < TokenStream , failure :: Error > {
20
33
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
+ } )
25
95
}
26
96
}
0 commit comments