Skip to content

Commit 808971b

Browse files
committed
wip
1 parent f8a4585 commit 808971b

File tree

3 files changed

+88
-46
lines changed

3 files changed

+88
-46
lines changed

graphql_client/tests/type_refining_fragments.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,12 @@ fn type_refining_fragment_on_union() {
5151
}
5252

5353
#[test]
54-
fn type_refining_fragment_on_query() {
54+
fn type_refining_fragment_on_interface() {
5555
use query_on_interface::*;
5656

57-
println!("{:?}", RESPONSE);
58-
let response_data: query_on_interface::ResponseData = serde_json::from_str(RESPONSE).unwrap();
57+
const RESPONSE: &'static str = include_str!("interfaces/interface_response.json");
5958

60-
println!("{:?}", response_data);
59+
let response_data: query_on_interface::ResponseData = serde_json::from_str(RESPONSE).unwrap();
6160

6261
let expected = ResponseData {
6362
everything: Some(vec![

graphql_client_codegen/src/interfaces.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use failure;
22
use objects::GqlObjectField;
33
use proc_macro2::{Ident, Span, TokenStream};
44
use query::QueryContext;
5-
use selection::{Selection, SelectionItem};
5+
use selection::{Selection, SelectionFragmentSpread, SelectionItem};
66
use shared::*;
77
use std::borrow::Cow;
88
use std::cell::Cell;
@@ -23,15 +23,25 @@ pub struct GqlInterface {
2323

2424
impl GqlInterface {
2525
/// filters the selection to keep only the fields that refer to the interface's own.
26-
fn object_selection(&self, selection: &Selection) -> Selection {
26+
fn object_selection(&self, selection: &Selection, query_context: &QueryContext) -> Selection {
2727
Selection(
2828
selection
2929
.0
3030
.iter()
3131
// Only keep what we can handle
3232
.filter(|f| match f {
3333
SelectionItem::Field(f) => f.name != "__typename",
34-
SelectionItem::FragmentSpread(_) => true,
34+
SelectionItem::FragmentSpread(SelectionFragmentSpread { fragment_name }) => {
35+
// only if the fragment refers to the interface’s own fields (to take into account type-refining fragments)
36+
let fragment = query_context
37+
.fragments
38+
.get(fragment_name)
39+
.ok_or_else(|| format_err!("Unknown fragment: {}", &fragment_name))
40+
// TODO: fix this
41+
.unwrap();
42+
43+
fragment.on == self.name
44+
}
3545
SelectionItem::InlineFragment(_) => false,
3646
}).map(|a| (*a).clone())
3747
.collect(),
@@ -59,7 +69,7 @@ impl GqlInterface {
5969
::shared::field_impls_for_selection(
6070
&self.fields,
6171
context,
62-
&self.object_selection(selection),
72+
&self.object_selection(selection, context),
6373
prefix,
6474
)
6575
}
@@ -75,7 +85,7 @@ impl GqlInterface {
7585
&self.name,
7686
&self.fields,
7787
context,
78-
&self.object_selection(selection),
88+
&self.object_selection(selection, context),
7989
prefix,
8090
)
8191
}
@@ -100,8 +110,8 @@ impl GqlInterface {
100110
.iter()
101111
// Only keep what we can handle
102112
.filter(|f| match f {
103-
SelectionItem::InlineFragment(_) => true,
104-
SelectionItem::Field(_) | SelectionItem::FragmentSpread(_) => false,
113+
SelectionItem::InlineFragment(_) | SelectionItem::FragmentSpread(_) => true,
114+
SelectionItem::Field(_) => false,
105115
}).map(|a| (*a).clone())
106116
.collect(),
107117
);

graphql_client_codegen/src/unions.rs

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use constants::*;
22
use failure;
33
use proc_macro2::{Ident, Span, TokenStream};
44
use query::QueryContext;
5-
use selection::{Selection, SelectionItem};
5+
use selection::{Selection, SelectionFragmentSpread, SelectionItem};
66
use std::cell::Cell;
77
use std::collections::BTreeSet;
88

@@ -45,40 +45,73 @@ pub(crate) fn union_variants(
4545
} else {
4646
true
4747
}
48-
}).map(|item| {
49-
match item {
50-
SelectionItem::Field(_) => Err(format_err!("field selection on union"))?,
51-
SelectionItem::FragmentSpread(_) => Err(format_err!("fragment spread on union"))?,
52-
SelectionItem::InlineFragment(frag) => {
53-
let variant_name = Ident::new(&frag.on, Span::call_site());
54-
used_variants.push(frag.on.to_string());
55-
56-
let new_prefix = format!("{}On{}", prefix, frag.on);
57-
58-
let variant_type = Ident::new(&new_prefix, Span::call_site());
59-
60-
let field_object_type = query_context.schema.objects.get(&frag.on).map(|_f| {
61-
query_context.maybe_expand_field(&frag.on, &frag.fields, &new_prefix)
62-
});
63-
let field_interface = query_context.schema.interfaces.get(&frag.on).map(|_f| {
64-
query_context.maybe_expand_field(&frag.on, &frag.fields, &new_prefix)
65-
});
66-
// nested unions, is that even a thing?
67-
let field_union_type = query_context.schema.unions.get(&frag.on).map(|_f| {
68-
query_context.maybe_expand_field(&frag.on, &frag.fields, &new_prefix)
69-
});
70-
71-
match field_object_type.or(field_interface).or(field_union_type) {
72-
Some(tokens) => children_definitions.push(tokens?),
73-
None => Err(UnionError::UnknownType {
74-
ty: frag.on.to_string(),
75-
})?,
76-
};
77-
78-
Ok(quote! {
79-
#variant_name(#variant_type)
80-
})
81-
}
48+
}).map(|item| match item {
49+
SelectionItem::Field(_) => Err(format_err!("field selection on union"))?,
50+
SelectionItem::FragmentSpread(SelectionFragmentSpread { fragment_name }) => {
51+
let fragment = query_context
52+
.fragments
53+
.get(fragment_name)
54+
.ok_or_else(|| format_err!("Unknown fragment: {}", &fragment_name))?;
55+
56+
let variant_name = Ident::new(&fragment.on, Span::call_site());
57+
used_variants.push(fragment.on.to_string());
58+
59+
let new_prefix = format!("{}On{}", prefix, fragment.on);
60+
61+
let variant_type = Ident::new(&new_prefix, Span::call_site());
62+
63+
let field_object_type = query_context.schema.objects.get(&fragment.on).map(|_f| {
64+
query_context.maybe_expand_field(&fragment.on, &fragment.selection, &new_prefix)
65+
});
66+
67+
let field_interface = query_context.schema.interfaces.get(&fragment.on).map(|_f| {
68+
query_context.maybe_expand_field(&fragment.on, &fragment.selection, &new_prefix)
69+
});
70+
71+
let field_union_type = query_context.schema.unions.get(&fragment.on).map(|_f| {
72+
query_context.maybe_expand_field(&fragment.on, &fragment.selection, &new_prefix)
73+
});
74+
75+
match field_object_type.or(field_interface).or(field_union_type) {
76+
Some(tokens) => children_definitions.push(tokens?),
77+
None => Err(UnionError::UnknownType {
78+
ty: fragment.on.to_string(),
79+
})?,
80+
};
81+
82+
Ok(quote! {
83+
#variant_name(#variant_type)
84+
})
85+
}
86+
SelectionItem::InlineFragment(frag) => {
87+
let variant_name = Ident::new(&frag.on, Span::call_site());
88+
used_variants.push(frag.on.to_string());
89+
90+
let new_prefix = format!("{}On{}", prefix, frag.on);
91+
92+
let variant_type = Ident::new(&new_prefix, Span::call_site());
93+
94+
let field_object_type = query_context.schema.objects.get(&frag.on).map(|_f| {
95+
query_context.maybe_expand_field(&frag.on, &frag.fields, &new_prefix)
96+
});
97+
let field_interface = query_context.schema.interfaces.get(&frag.on).map(|_f| {
98+
query_context.maybe_expand_field(&frag.on, &frag.fields, &new_prefix)
99+
});
100+
101+
let field_union_type = query_context.schema.unions.get(&frag.on).map(|_f| {
102+
query_context.maybe_expand_field(&frag.on, &frag.fields, &new_prefix)
103+
});
104+
105+
match field_object_type.or(field_interface).or(field_union_type) {
106+
Some(tokens) => children_definitions.push(tokens?),
107+
None => Err(UnionError::UnknownType {
108+
ty: frag.on.to_string(),
109+
})?,
110+
};
111+
112+
Ok(quote! {
113+
#variant_name(#variant_type)
114+
})
82115
}
83116
}).collect();
84117

0 commit comments

Comments
 (0)