Skip to content

Commit

Permalink
SDL - Separate multiple inherited interfaces with & (#309)
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegIlyenko committed Feb 5, 2018
1 parent 3c07621 commit 4f8bc41
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 15 deletions.
25 changes: 18 additions & 7 deletions src/main/scala/sangria/parser/QueryParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ trait Document { this: Parser with Operations with Ignored with Fragments with O
}

trait TypeSystemDefinitions { this: Parser with Tokens with Ignored with Directives with Types with Operations with Values with Fragments
def legacyImplementsInterface: Boolean

def scalar = rule { Keyword("scalar") }
def `type` = rule { Keyword("type") }
Expand Down Expand Up @@ -196,7 +197,10 @@ trait TypeSystemDefinitions { this: Parser with Tokens with Ignored with Directi
(descr, comment, pos, name, interfaces) ast.TypeExtensionDefinition(ast.ObjectTypeDefinition(name, interfaces, Vector.empty, Vector.empty, descr, comment, Vector.empty, Some(pos)), Vector.empty, Some(pos))))
}

def ImplementsInterfaces = rule { implements ~ NamedType.+ ~> (_.toVector) }
def ImplementsInterfaces = rule {
test(legacyImplementsInterface) ~ implements ~ NamedType.+ ~> (_.toVector) |
implements ~ ws('&').? ~ NamedType.+(ws('&')) ~> (_.toVector)
}

def FieldDefinitions = rule {
wsNoComment('{') ~ FieldDefinition.+ ~ Comments ~ wsNoComment('}')
Expand Down Expand Up @@ -417,15 +421,22 @@ trait Types { this: Parser with Tokens with Ignored ⇒
}
}

class QueryParser private (val input: ParserInput)
class QueryParser private (val input: ParserInput, val legacyImplementsInterface: Boolean = false, val legacyEmptyFields: Boolean = false)
extends Parser with Tokens with Ignored with Document with Operations with Fragments with Values with Directives with Types with TypeSystemDefinitions

object QueryParser {
def parse(input: String)(implicit scheme: DeliveryScheme[ast.Document]): scheme.Result =
parse(ParserInput(input))(scheme)

def parse(input: ParserInput)(implicit scheme: DeliveryScheme[ast.Document]): scheme.Result = {
val parser = new QueryParser(input)
def parse(
input: String,
@deprecated("Use new syntax: `type Foo implements Bar & Baz`", "1.3.4")
legacyImplementsInterface: Boolean = false,
@deprecated("Use new syntax: `type Foo` intead of legacy `type Foo {}`", "1.3.4")
legacyEmptyFields: Boolean = false
)(implicit scheme: DeliveryScheme[ast.Document]): scheme.Result = {
parse(ParserInput(input), legacyImplementsInterface, legacyEmptyFields)(scheme)
}

def parse(input: ParserInput, legacyImplementsInterface: Boolean, legacyEmptyFields: Boolean)(implicit scheme: DeliveryScheme[ast.Document]): scheme.Result = {
val parser = new QueryParser(input, legacyImplementsInterface, legacyEmptyFields)

parser.Document.run() match {
case Success(res)
Expand Down
14 changes: 9 additions & 5 deletions src/main/scala/sangria/renderer/QueryRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ object QueryRenderer {
inputListSeparator = ",",
formatInputValues = false,
renderComments = true,
formatBlockStrings = true)
formatBlockStrings = true,
legacyImplementsInterface = false)

val PrettyInput = Pretty.copy(
inputFieldSeparator = "\n",
formatInputValues = true,
renderComments = true)
renderComments = true,
legacyImplementsInterface = false)

val Compact = QueryRendererConfig(
indentLevel = "",
Expand All @@ -34,7 +36,8 @@ object QueryRenderer {
inputListSeparator = ",",
formatInputValues = false,
renderComments = false,
formatBlockStrings = false)
formatBlockStrings = false,
legacyImplementsInterface = false)

def renderSelections(sels: Vector[Selection], tc: WithTrailingComments, indent: Indent, config: QueryRendererConfig) =
if (sels.nonEmpty) {
Expand Down Expand Up @@ -150,7 +153,7 @@ object QueryRenderer {
if (interfaces.nonEmpty)
(if (frontSep) config.mandatorySeparator else "") +
"implements" + config.mandatorySeparator +
(interfaces map (renderNode(_, config, indent.zero)) mkString ("," + config.separator)) +
(interfaces map (renderNode(_, config, indent.zero)) mkString (if (config.legacyImplementsInterface) "," + config.separator else config.separator + "&" + config.separator )) +
(if (withSep) config.separator else "")
else ""

Expand Down Expand Up @@ -563,4 +566,5 @@ case class QueryRendererConfig(
inputListSeparator: String,
formatInputValues: Boolean,
formatBlockStrings: Boolean,
renderComments: Boolean)
renderComments: Boolean,
legacyImplementsInterface: Boolean)
60 changes: 59 additions & 1 deletion src/test/scala/sangria/parser/SchemaParserSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,65 @@ class SchemaParserSpec extends WordSpec with Matchers with StringMatchers {

"Simple type inheriting multiple interfaces" in {
val Success(ast) = QueryParser.parse(
"type Hello implements Wo, rld { foo: Bar }")
"type Hello implements Wo & rld { foo: Bar }")

ast.copy(sourceMapper = None) should be (
Document(
Vector(
ObjectTypeDefinition(
"Hello",
Vector(
NamedType("Wo", Some(Position(22, 1, 23))),
NamedType("rld", Some(Position(27, 1, 28)))),
Vector(
FieldDefinition("foo", NamedType("Bar", Some(Position(38, 1, 39))), Vector.empty, Vector.empty, None, Vector.empty, Some(Position(33, 1, 34)))),
Vector.empty,
None,
Vector.empty,
Vector.empty,
Some(Position(0, 1, 1))
)),
Vector.empty,
Some(Position(0, 1, 1)),
None
))
}

"Simple type inheriting multiple interfaces (allow separator at the beginning)" in {
val Success(ast) = QueryParser.parse(
"""
type Hello implements
& Foo
& Baz
{
foo: Bar
}
""")
ast.copy(sourceMapper = None) should be (
Document(
Vector(
ObjectTypeDefinition(
"Hello",
Vector(
NamedType("Foo", Some(Position(47, 3, 15))),
NamedType("Baz", Some(Position(65, 4, 15)))),
Vector(
FieldDefinition("foo", NamedType("Bar", Some(Position(98, 6, 18))), Vector.empty, Vector.empty, None, Vector.empty, Some(Position(93, 6, 13)))),
Vector.empty,
None,
Vector.empty,
Vector.empty,
Some(Position(11, 2, 11))
)),
Vector.empty,
Some(Position(11, 2, 11)),
None
))
}

"Simple type inheriting multiple interfaces (legacy syntax)" in {
val Success(ast) = QueryParser.parse(
"type Hello implements Wo, rld { foo: Bar }", legacyImplementsInterface = true)

ast.copy(sourceMapper = None) should be (
Document(
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/sangria/renderer/SchemaRenderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ class SchemaRenderSpec extends WordSpec with Matchers with FutureResultSupport w
| int: Int
|}
|
|type Bar implements Foo, Baaz {
|type Bar implements Foo & Baaz {
| str: String
| int: Int
|}
Expand Down Expand Up @@ -341,7 +341,7 @@ class SchemaRenderSpec extends WordSpec with Matchers with FutureResultSupport w
| str: String
|}
|
|type Bar implements Baaz, Foo {
|type Bar implements Baaz & Foo {
| int: Int
| str: String
|}
Expand Down

0 comments on commit 4f8bc41

Please sign in to comment.