From a79a51d4455f770a1ad824089ee906a26cd5c29c Mon Sep 17 00:00:00 2001 From: Vladimir Razuvaev Date: Wed, 5 Jul 2017 18:42:27 +0700 Subject: [PATCH] Schema Parsing: allow leading pipe for union type definitions --- src/Language/Parser.php | 7 +- tests/Language/SchemaParserTest.php | 100 +++++++++++++++++---- tests/Language/SchemaPrinterTest.php | 4 + tests/Language/schema-kitchen-sink.graphql | 7 ++ 4 files changed, 98 insertions(+), 20 deletions(-) diff --git a/src/Language/Parser.php b/src/Language/Parser.php index e19f667..76c5d1b 100644 --- a/src/Language/Parser.php +++ b/src/Language/Parser.php @@ -1080,14 +1080,17 @@ class Parser /** * UnionMembers : - * - NamedType + * - `|`? NamedType * - UnionMembers | NamedType * * @return NamedTypeNode[] */ function parseUnionMembers() { + // Optional leading pipe + $this->skip(Token::PIPE); $members = []; + do { $members[] = $this->parseNamedType(); } while ($this->skip(Token::PIPE)); @@ -1213,6 +1216,8 @@ class Parser */ function parseDirectiveLocations() { + // Optional leading pipe + $this->skip(Token::PIPE); $locations = []; do { $locations[] = $this->parseName(); diff --git a/tests/Language/SchemaParserTest.php b/tests/Language/SchemaParserTest.php index 736ebf9..029ec4f 100644 --- a/tests/Language/SchemaParserTest.php +++ b/tests/Language/SchemaParserTest.php @@ -1,27 +1,9 @@ assertEquals($expected, TestUtils::nodeToArray($doc)); } + + /** + * @it Union with two types and leading pipe + */ + public function testUnionWithTwoTypesAndLeadingPipe() + { + $body = 'union Hello = | Wo | Rld'; + $doc = Parser::parse($body); + $expected = [ + 'kind' => 'Document', + 'definitions' => [ + [ + 'kind' => 'UnionTypeDefinition', + 'name' => $this->nameNode('Hello', ['start' => 6, 'end' => 11]), + 'directives' => [], + 'types' => [ + $this->typeNode('Wo', ['start' => 16, 'end' => 18]), + $this->typeNode('Rld', ['start' => 21, 'end' => 24]), + ], + 'loc' => ['start' => 0, 'end' => 24], + 'description' => null + ] + ], + 'loc' => ['start' => 0, 'end' => 24], + ]; + $this->assertEquals($expected, TestUtils::nodeToArray($doc)); + } + + /** + * @it Union fails with no types + */ + public function testUnionFailsWithNoTypes() + { + $body = 'union Hello = |'; + try { + Parser::parse($body); + } catch (SyntaxError $e) { + $this->assertContains('Syntax Error GraphQL (1:16) Expected Name, found ', $e->getMessage()); + } + } + + /** + * @it Union fails with leading douple pipe + */ + public function testUnionFailsWithLeadingDoublePipe() + { + $body = 'union Hello = || Wo | Rld'; + try { + Parser::parse($body); + } catch (SyntaxError $e) { + $this->assertContains('Syntax Error GraphQL (1:16) Expected Name, found |', $e->getMessage()); + } + } + + /** + * @it Union fails with double pipe + */ + public function testUnionFailsWithDoublePipe() + { + $body = 'union Hello = Wo || Rld'; + try { + Parser::parse($body); + } catch (SyntaxError $e) { + $this->assertContains('Syntax Error GraphQL (1:19) Expected Name, found |', $e->getMessage()); + } + } + + /** + * @it Union fails with trailing pipe + */ + public function testUnionFailsWithTrailingPipe() + { + $body = 'union Hello = | Wo | Rld |'; + try { + Parser::parse($body); + } catch (SyntaxError $e) { + $this->assertContains('Syntax Error GraphQL (1:27) Expected Name, found ', $e->getMessage()); + } + } + /** * @it Scalar */ diff --git a/tests/Language/SchemaPrinterTest.php b/tests/Language/SchemaPrinterTest.php index 29c0f10..a649ced 100644 --- a/tests/Language/SchemaPrinterTest.php +++ b/tests/Language/SchemaPrinterTest.php @@ -83,6 +83,8 @@ union Feed = Story | Article | Advert union AnnotatedUnion @onUnion = A | B +union AnnotatedUnionTwo @onUnion = A | B + scalar CustomScalar scalar AnnotatedScalar @onScalar @@ -117,6 +119,8 @@ type NoFields {} directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT + +directive @include2(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT '; $this->assertEquals($expected, $printed); } diff --git a/tests/Language/schema-kitchen-sink.graphql b/tests/Language/schema-kitchen-sink.graphql index a56c0e4..0544266 100644 --- a/tests/Language/schema-kitchen-sink.graphql +++ b/tests/Language/schema-kitchen-sink.graphql @@ -37,6 +37,8 @@ union Feed = Story | Article | Advert union AnnotatedUnion @onUnion = A | B +union AnnotatedUnionTwo @onUnion = | A | B + scalar CustomScalar scalar AnnotatedScalar @onScalar @@ -74,3 +76,8 @@ directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT + +directive @include2(if: Boolean!) on + | FIELD + | FRAGMENT_SPREAD + | INLINE_FRAGMENT