Skip to content
This repository has been archived by the owner on Oct 26, 2020. It is now read-only.

Commit

Permalink
Allow directives on variable definitions. Closes sangria-graphql#396
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegIlyenko committed Oct 6, 2018
1 parent aa020cd commit 65ffe26
Show file tree
Hide file tree
Showing 19 changed files with 100 additions and 36 deletions.
6 changes: 4 additions & 2 deletions src/main/scala/sangria/ast/QueryAst.scala
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@ case class VariableDefinition(
name: String,
tpe: Type,
defaultValue: Option[Value],
directives: Vector[Directive] = Vector.empty,
comments: Vector[Comment] = Vector.empty,
location: Option[AstLocation] = None) extends AstNode with WithComments
location: Option[AstLocation] = None) extends AstNode with WithComments with WithDirectives

sealed trait Type extends AstNode {
def namedType: NamedType = {
Expand Down Expand Up @@ -652,10 +653,11 @@ object AstVisitor {
trailingComments.foreach(s loop(s))
breakOrSkip(onLeave(n))
}
case n @ VariableDefinition(_, tpe, default, comment, _)
case n @ VariableDefinition(_, tpe, default, dirs, comment, _)
if (breakOrSkip(onEnter(n))) {
loop(tpe)
default.foreach(d loop(d))
dirs.foreach(d loop(d))
comment.foreach(s loop(s))
breakOrSkip(onLeave(n))
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/sangria/execution/batch/BatchExecutor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ object BatchExecutor {
if (violations.nonEmpty)
inferenceViolations ++= violations
else
newVariableDefs += ast.VariableDefinition(ud, firstAstType, None, Vector(ast.Comment("Inferred variable")))
newVariableDefs += ast.VariableDefinition(ud, firstAstType, None, Vector.empty, Vector(ast.Comment("Inferred variable")))
}

if (newVariableDefs.nonEmpty && inferenceViolations.isEmpty)
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/sangria/introspection/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ package object introspection {
description = Some("Location adjacent to a fragment spread.")),
EnumValue("INLINE_FRAGMENT", value = DirectiveLocation.InlineFragment,
description = Some("Location adjacent to an inline fragment.")),
EnumValue("VARIABLE_DEFINITION", value = DirectiveLocation.VariableDefinition,
description = Some("Location adjacent to a variable definition.")),

EnumValue("SCHEMA", value = DirectiveLocation.Schema,
description = Some("Location adjacent to a schema definition.")),
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/sangria/macros/AstLiftable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ trait AstLiftable {
}

implicit def liftVarDef: Liftable[VariableDefinition] = Liftable {
case VariableDefinition(n, t, d, c, p)
q"_root_.sangria.ast.VariableDefinition($n, $t, $d, $c, $p)"
case VariableDefinition(n, t, d, dirs, c, p)
q"_root_.sangria.ast.VariableDefinition($n, $t, $d, $dirs, $c, $p)"
}

implicit def liftInpValDef: Liftable[InputValueDefinition] = Liftable {
Expand Down
7 changes: 4 additions & 3 deletions src/main/scala/sangria/parser/QueryParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,8 @@ trait TypeSystemDefinitions { this: Parser with Tokens with Ignored with Directi
wsCapture("ENUM_VALUE") |
wsCapture("ENUM") |
wsCapture("INPUT_OBJECT") |
wsCapture("INPUT_FIELD_DEFINITION")
wsCapture("INPUT_FIELD_DEFINITION") |
wsCapture("VARIABLE_DEFINITION")
}

def SchemaDefinition = rule {
Expand Down Expand Up @@ -395,8 +396,8 @@ trait Operations extends PositionTracking { this: Parser with Tokens with Ignore

def VariableDefinitions = rule { wsNoComment('(') ~ VariableDefinition.+ ~ wsNoComment(')') ~> (_.toVector)}

def VariableDefinition = rule { Comments ~ trackPos ~ Variable ~ ws(':') ~ Type ~ DefaultValue.? ~>
((comment, location, name, tpe, defaultValue) ast.VariableDefinition(name, tpe, defaultValue, comment, location)) }
def VariableDefinition = rule { Comments ~ trackPos ~ Variable ~ ws(':') ~ Type ~ DefaultValue.? ~ (DirectivesConst.? ~> (_ getOrElse Vector.empty)) ~>
((comment, location, name, tpe, defaultValue, dirs) ast.VariableDefinition(name, tpe, defaultValue, dirs, comment, location)) }

def Variable = rule { Ignored.* ~ '$' ~ NameStrict }

Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/sangria/renderer/QueryRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,12 @@ object QueryRenderer {
renderDirs(dirs, config, indent) +
renderSelections(sels, fd, indent, config)

case vd @ VariableDefinition(name, tpe, defaultValue, _, _)
case vd @ VariableDefinition(name, tpe, defaultValue, dirs, _, _)
renderComment(vd, prev, indent, config) +
indent.str + "$" + name + ":" + config.separator +
renderNode(tpe, config, indent.zero) +
(defaultValue map (v config.separator + "=" + config.separator + renderNode(v, config, indent.zero)) getOrElse "")
(defaultValue map (v config.separator + "=" + config.separator + renderNode(v, config, indent.zero)) getOrElse "") +
renderDirs(dirs, config, indent, frontSep = true)

case NotNullType(ofType, _)
renderNode(ofType, config, indent.zero) + "!"
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/sangria/schema/Schema.scala
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,7 @@ object DirectiveLocation extends Enumeration {
val Schema = Value
val Subscription = Value
val Union = Value
val VariableDefinition = Value

def fromString(location: String): DirectiveLocation.Value = location match {
case "QUERY" Query
Expand All @@ -707,6 +708,7 @@ object DirectiveLocation extends Enumeration {
case "FRAGMENT_DEFINITION" FragmentDefinition
case "FRAGMENT_SPREAD" FragmentSpread
case "INLINE_FRAGMENT" InlineFragment
case "VARIABLE_DEFINITION" VariableDefinition

case "SCHEMA" Schema
case "SCALAR" Scalar
Expand All @@ -729,6 +731,7 @@ object DirectiveLocation extends Enumeration {
case FragmentDefinition "FRAGMENT_DEFINITION"
case FragmentSpread "FRAGMENT_SPREAD"
case InlineFragment "INLINE_FRAGMENT"
case VariableDefinition "VARIABLE_DEFINITION"

case Schema "SCHEMA"
case Scalar "SCALAR"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ object KnownDirectives {
case _: ast.FragmentDefinition Some(DirectiveLocation.FragmentDefinition "fragment definition")
case _: ast.FragmentSpread Some(DirectiveLocation.FragmentSpread "fragment spread")
case _: ast.InlineFragment Some(DirectiveLocation.InlineFragment "inline fragment")
case _: ast.VariableDefinition Some(DirectiveLocation.VariableDefinition "variable definition")

case _: ast.SchemaDefinition Some(DirectiveLocation.Schema "schema definition")
case _: ast.SchemaExtensionDefinition Some(DirectiveLocation.Schema "schema extension definition")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class UniqueVariableNames extends ValidationRule {
knownVariableNames.clear()
AstVisitorCommand.RightContinue

case ast.VariableDefinition(name, _, _, _, pos)
case ast.VariableDefinition(name, _, _, _, _, pos)
knownVariableNames get name match {
case Some(otherPos)
Left(Vector(DuplicateVariableViolation(name, ctx.sourceMapper, otherPos ++ pos.toList)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import sangria.validation._
class VariablesAreInputTypes extends ValidationRule {
override def visitor(ctx: ValidationContext) = new AstValidatingVisitor {
override val onEnter: ValidationVisit = {
case ast.VariableDefinition(name, tpe, _, _, pos)
case ast.VariableDefinition(name, tpe, _, _, _, pos)
ctx.schema.getInputType(tpe) match {
case Some(_) AstVisitorCommand.RightContinue
case None Left(Vector(
Expand Down
19 changes: 13 additions & 6 deletions src/test/resources/scenarios/validation/KnownDirectives.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ tests:
- name: with well placed directives
given:
query: |-
query Foo @onQuery {
name @include(if: true)
query Foo($var: Boolean @onVariableDefinition) @onQuery {
name @include(if: $var)
...Frag @include(if: true)
skippedField @skip(if: true)
...SkippedFrag @skip(if: true)
Expand All @@ -111,8 +111,8 @@ tests:
- name: with misplaced directives
given:
query: |-
query Foo @include(if: true) {
name @onQuery
query Foo($var: Boolean @onField) @include(if: true) {
name @onQuery @include(if: $var)
...Frag @onQuery
}
Expand All @@ -123,14 +123,21 @@ tests:
validate:
- KnownDirectives
then:
- error-count: 4
- error-count: 5
- error-code: misplacedDirective
args:
directiveName: onField
location: VARIABLE_DEFINITION
loc:
line: 1
column: 25
- error-code: misplacedDirective
args:
directiveName: include
location: QUERY
loc:
line: 1
column: 11
column: 35
- error-code: misplacedDirective
args:
directiveName: onQuery
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ directive @onField on FIELD
directive @onFragmentDefinition on FRAGMENT_DEFINITION
directive @onFragmentSpread on FRAGMENT_SPREAD
directive @onInlineFragment on INLINE_FRAGMENT
directive @onVariableDefinition on VARIABLE_DEFINITION
directive @onSchema on SCHEMA
directive @onScalar on SCALAR
directive @onObject on OBJECT
Expand Down
5 changes: 5 additions & 0 deletions src/test/scala/sangria/introspection/IntrospectionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ class IntrospectionSpec extends WordSpec with Matchers with FutureResultSupport
"description" "Location adjacent to an inline fragment.",
"isDeprecated" false,
"deprecationReason" null),
Map(
"name" "VARIABLE_DEFINITION",
"description" "Location adjacent to a variable definition.",
"isDeprecated" false,
"deprecationReason" null),
Map(
"name" "SCHEMA",
"description" "Location adjacent to a schema definition.",
Expand Down
5 changes: 5 additions & 0 deletions src/test/scala/sangria/macros/LiteralMacroSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ class LiteralMacroSpec extends WordSpec with Matchers {
NamedType("Int", None),
Some(BigDecimalValue(1.23, Vector.empty, None)),
Vector.empty,
Vector.empty,
None
),
VariableDefinition(
"anotherVar",
NamedType("Int", None),
Some(BigIntValue(123, Vector.empty, None)),
Vector.empty,
Vector.empty,
None
)),
Vector(
Expand Down Expand Up @@ -300,13 +302,15 @@ class LiteralMacroSpec extends WordSpec with Matchers {
NamedType("ComplexType", None),
None,
Vector.empty,
Vector.empty,
None
),
VariableDefinition(
"site",
NamedType("Site", None),
Some(EnumValue("MOBILE", Vector.empty, None)),
Vector.empty,
Vector.empty,
None
)),
Vector.empty,
Expand Down Expand Up @@ -441,6 +445,7 @@ class LiteralMacroSpec extends WordSpec with Matchers {
NamedType("StoryLikeSubscribeInput", None),
None,
Vector.empty,
Vector.empty,
None
)),
Vector.empty,
Expand Down
Loading

0 comments on commit 65ffe26

Please sign in to comment.