Skip to content

Commit 23643fb

Browse files
committed
Extract union variant codegen to utility function
We are going to use it for interfaces
1 parent 4bfd3ac commit 23643fb

File tree

3 files changed

+52
-25
lines changed

3 files changed

+52
-25
lines changed

graphql_query_derive/src/constants.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ pub const TYPENAME_FIELD: &'static str = "__typename";
55
pub fn string_type() -> Ident {
66
Ident::new("String", Span::call_site())
77
}
8+
9+
pub fn float_type() -> Ident {
10+
Ident::new("Float", Span::call_site())
11+
}

graphql_query_derive/src/selection.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use constants::*;
12
use graphql_parser::query::SelectionSet;
23

34
#[derive(Debug, PartialEq)]
@@ -24,9 +25,26 @@ pub enum SelectionItem {
2425
InlineFragment(SelectionInlineFragment),
2526
}
2627

28+
impl SelectionItem {
29+
pub fn as_typename(&self) -> Option<&SelectionField> {
30+
if let SelectionItem::Field(f) = self {
31+
if f.name == TYPENAME_FIELD {
32+
return Some(f);
33+
}
34+
}
35+
None
36+
}
37+
}
38+
2739
#[derive(Debug, PartialEq)]
2840
pub struct Selection(pub Vec<SelectionItem>);
2941

42+
impl Selection {
43+
pub fn extract_typename(&self) -> Option<&SelectionField> {
44+
self.0.iter().filter_map(|f| f.as_typename()).next()
45+
}
46+
}
47+
3048
impl<'a> ::std::convert::From<&'a SelectionSet> for Selection {
3149
fn from(selection_set: &SelectionSet) -> Selection {
3250
use graphql_parser::query::Selection;

graphql_query_derive/src/unions.rs

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,14 @@ enum UnionError {
1717
MissingTypename { union_name: String },
1818
}
1919

20-
impl GqlUnion {
21-
pub fn response_for_selection(
22-
&self,
23-
query_context: &QueryContext,
24-
selection: &Selection,
25-
prefix: &str,
26-
) -> Result<TokenStream, failure::Error> {
27-
let struct_name = Ident::new(prefix, Span::call_site());
28-
let mut children_definitions: Vec<TokenStream> = Vec::new();
29-
30-
let typename_field = selection.0.iter().find(|f| {
31-
if let SelectionItem::Field(f) = f {
32-
f.name == TYPENAME_FIELD
33-
} else {
34-
false
35-
}
36-
});
20+
pub fn union_variants(
21+
selection: &Selection,
22+
query_context: &QueryContext,
23+
prefix: &str,
24+
) -> Result<(Vec<TokenStream>, Vec<TokenStream>), failure::Error> {
25+
let mut children_definitions = Vec::new();
3726

38-
if typename_field.is_none() {
39-
Err(UnionError::MissingTypename {
40-
union_name: prefix.into(),
41-
})?;
42-
}
43-
44-
let variants: Result<Vec<TokenStream>, failure::Error> = selection
27+
let variants: Result<Vec<TokenStream>, failure::Error> = selection
4528
.0
4629
.iter()
4730
// ignore __typename
@@ -98,7 +81,29 @@ impl GqlUnion {
9881
})
9982
.collect();
10083

101-
let variants = variants?;
84+
let variants = variants?;
85+
86+
Ok((variants, children_definitions))
87+
}
88+
89+
impl GqlUnion {
90+
pub fn response_for_selection(
91+
&self,
92+
query_context: &QueryContext,
93+
selection: &Selection,
94+
prefix: &str,
95+
) -> Result<TokenStream, failure::Error> {
96+
let struct_name = Ident::new(prefix, Span::call_site());
97+
98+
let typename_field = selection.extract_typename();
99+
100+
if typename_field.is_none() {
101+
Err(UnionError::MissingTypename {
102+
union_name: prefix.into(),
103+
})?;
104+
}
105+
106+
let (variants, children_definitions) = union_variants(selection, query_context, prefix)?;
102107

103108
Ok(quote!{
104109
#(#children_definitions)*

0 commit comments

Comments
 (0)