From 664fc0e94a8cd8fa20427990190c75ba824cec92 Mon Sep 17 00:00:00 2001 From: Lee Byron Date: Thu, 1 Oct 2015 16:07:53 -0700 Subject: [PATCH] [RFC] Type condition optional on inline fragments. Originally proposed by @josephsavona, this allows inline fragments to omit a type condition and thus always be considered for inclusion. If a type condition is omitted, no type refinement is done to the contained fields. This enables a new kind of usecase where the only purpose for using an inline fragment is applying a directive to a grouping of fields: ```graphql fragment Foo on Type { fieldA fieldB ... @include(if: $wat) { fieldC fieldD } } ``` --- spec/Appendix B -- Grammar Summary.md | 6 +++--- spec/Section 2 -- Language.md | 24 +++++++++++++++++++++--- spec/Section 5 -- Validation.md | 6 ++++++ spec/Section 6 -- Execution.md | 2 +- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/spec/Appendix B -- Grammar Summary.md b/spec/Appendix B -- Grammar Summary.md index 5a5c644aa..1cccaaf3d 100644 --- a/spec/Appendix B -- Grammar Summary.md +++ b/spec/Appendix B -- Grammar Summary.md @@ -113,13 +113,13 @@ Argument : Name : Value FragmentSpread : ... FragmentName Directives? -InlineFragment : ... on TypeCondition Directives? SelectionSet +InlineFragment : ... TypeCondition? Directives? SelectionSet -FragmentDefinition : fragment FragmentName on TypeCondition Directives? SelectionSet +FragmentDefinition : fragment FragmentName TypeCondition Directives? SelectionSet FragmentName : Name but not `on` -TypeCondition : NamedType +TypeCondition : on NamedType Value[Const] : - [~Const] Variable diff --git a/spec/Section 2 -- Language.md b/spec/Section 2 -- Language.md index 0d85b2b8b..afc55c172 100644 --- a/spec/Section 2 -- Language.md +++ b/spec/Section 2 -- Language.md @@ -431,7 +431,7 @@ otherwise the field's name. FragmentSpread : ... FragmentName Directives? -FragmentDefinition : fragment FragmentName on TypeCondition Directives? SelectionSet +FragmentDefinition : fragment FragmentName TypeCondition Directives? SelectionSet FragmentName : Name but not `on` @@ -519,7 +519,7 @@ produce the same response object. #### Type Conditions -TypeCondition : NamedType +TypeCondition : on NamedType Fragments must specify the type they apply to. In this example, `friendFields` can be used in the context of querying a `User`. @@ -578,7 +578,7 @@ will be present and `friends` will not. #### Inline Fragments -InlineFragment : ... on TypeCondition Directives? SelectionSet +InlineFragment : ... TypeCondition? Directives? SelectionSet Fragments can be defined inline within a selection set. This is done to conditionally include fields based on their runtime type. This feature of @@ -603,6 +603,24 @@ query inlineFragmentTyping { } ``` +Inline fragments may also be used to apply a directive to a group of fields. +If the TypeCondition is omitted, an inline fragment is considered to be of the +same type as the enclosing context. + +```graphql +query inlineFragmentNoType($expandedInfo: Boolean) { + user(handle: "zuck") { + id + name + ... @include(if: $expandedInfo) { + firstName + lastName + birthday + } + } +} +``` + ### Input Values diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index ba90c0fc3..0b3ca1155 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -650,6 +650,12 @@ fragment inlineFragment on Dog { name } } + +fragment inlineFragment on Dog { + ... @include(if: true) { + name + } +} ``` and the following do not validate: diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 5f45cb5e7..935fff9e3 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -77,7 +77,7 @@ CollectFields(objectType, selectionSet, visitedFragments): * Append all items in {fragmentGroup} to {groupForResponseKey}. * If {selection} is an inline fragment: * Let {fragmentType} be the type condition on {selection}. - * If {doesFragmentTypeApply(objectType, fragmentType)} is false, continue + * If {fragmentType} is not {null} and {doesFragmentTypeApply(objectType, fragmentType)} is false, continue with the next {selection} in {selectionSet}. * Let {fragmentSelectionSet} be the top-level selection set of {selection}. * Let {fragmentGroupedFields} be the result of calling {CollectFields(objectType, fragmentSelectionSet)}.