From b6334c25a0edf96277024669157fce316d276c2d Mon Sep 17 00:00:00 2001 From: Lee Byron Date: Fri, 28 Oct 2016 17:41:17 -0700 Subject: [PATCH] [RFC] Add Validation rule for unique directives per location. (#229) This rule was suggested by @jjergus (#223) to remove ambiguity from execution where the `@skip` and `@ignore` directive rules make the assumption that only one is defined per selection. In general I think this assumption should be upheld by valid queries overall, not just for `@skip` and `@include` so that it can be relied upon for any usage of directives. For example, this allows a potential optimization to use a hashmap keyed on directive name to represent the directives at a location rather than an array. Closes #223 --- spec/Section 5 -- Validation.md | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index 796af9987..ac61513c1 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -1242,6 +1242,49 @@ query @skip(if: $foo) { ``` +### Directives Are Unique Per Location + +** Formal Specification ** + + * For every {location} in the document for which Directives can apply: + * Let {directives} be the set of Directives which apply to {location}. + * For each {directive} in {directives}: + * Let {directiveName} be the name of {directive}. + * Let {namedDirectives} be the set of all Directives named {directiveName} + in {directives}. + * {namedDirectives} must be a set of one. + +** Explanatory Text ** + +Directives are used to describe some metadata or behavioral change on the +definition they apply to. When more than one directive of the same name is used, +the expected metadata or behavior becomes ambiguous, therefore only one of each +directive is allowed per location. + +For example, the following query will not pass validation because `@skip` has +been used twice for the same field: + +```!graphql +query ($foo: Boolean = true, $bar: Boolean = false) { + field @skip(if: $foo) @skip(if: $bar) +} +``` + +However the following example is valid because `@skip` has been used only once +per location, despite being used twice in the query and on the same named field: + +```graphql +query ($foo: Boolean = true, $bar: Boolean = false) { + field @skip(if: $foo) { + subfieldA + } + field @skip(if: $bar) { + subfieldB + } +} +``` + + ## Variables ### Variable Uniqueness