diff --git a/graphql_client/tests/fragment_chain.rs b/graphql_client/tests/fragment_chain.rs new file mode 100644 index 000000000..40c1e6fc8 --- /dev/null +++ b/graphql_client/tests/fragment_chain.rs @@ -0,0 +1,9 @@ +use graphql_client::*; + +#[allow(dead_code)] +#[derive(GraphQLQuery)] +#[graphql( + schema_path = "tests/fragment_chain/schema.graphql", + query_path = "tests/fragment_chain/query.graphql" +)] +struct Q; diff --git a/graphql_client/tests/fragment_chain/query.graphql b/graphql_client/tests/fragment_chain/query.graphql new file mode 100644 index 000000000..402d4d30a --- /dev/null +++ b/graphql_client/tests/fragment_chain/query.graphql @@ -0,0 +1,11 @@ +query Q { + ...FragmentB +} + +fragment FragmentB on Query { + ...FragmentA +} + +fragment FragmentA on Query { + x +} diff --git a/graphql_client/tests/fragment_chain/schema.graphql b/graphql_client/tests/fragment_chain/schema.graphql new file mode 100644 index 000000000..c54fb81e6 --- /dev/null +++ b/graphql_client/tests/fragment_chain/schema.graphql @@ -0,0 +1,3 @@ +type Query { + x: String +} diff --git a/graphql_client_codegen/src/fragments.rs b/graphql_client_codegen/src/fragments.rs index cd4f33c19..ac5c8d901 100644 --- a/graphql_client_codegen/src/fragments.rs +++ b/graphql_client_codegen/src/fragments.rs @@ -56,4 +56,9 @@ impl<'query> GqlFragment<'query> { pub(crate) fn is_recursive(&self) -> bool { self.selection.contains_fragment(&self.name) } + + pub(crate) fn require<'schema>(&self, context: &QueryContext<'query, 'schema>) { + self.is_required.set(true); + self.selection.require_items(context); + } } diff --git a/graphql_client_codegen/src/query.rs b/graphql_client_codegen/src/query.rs index e7d8f8ef8..15aef89d1 100644 --- a/graphql_client_codegen/src/query.rs +++ b/graphql_client_codegen/src/query.rs @@ -40,7 +40,7 @@ impl<'query, 'schema> QueryContext<'query, 'schema> { /// Mark a fragment as required, so code is actually generated for it. pub(crate) fn require_fragment(&self, typename_: &str) { if let Some(fragment) = self.fragments.get(typename_) { - fragment.is_required.set(true) + fragment.require(&self); } } diff --git a/graphql_client_codegen/src/selection.rs b/graphql_client_codegen/src/selection.rs index 5095f4bdf..720bcefc6 100644 --- a/graphql_client_codegen/src/selection.rs +++ b/graphql_client_codegen/src/selection.rs @@ -167,6 +167,14 @@ impl<'query> Selection<'query> { pub(crate) fn len(&self) -> usize { self.0.len() } + + pub(crate) fn require_items<'s>(&self, context: &crate::query::QueryContext<'query, 's>) { + self.0.iter().for_each(|item| { + if let SelectionItem::FragmentSpread(SelectionFragmentSpread { fragment_name }) = item { + context.require_fragment(fragment_name); + } + }) + } } impl<'query> std::convert::From<&'query SelectionSet> for Selection<'query> {