From bbb5cf1e4dfaf55dce3651104210c0741870deb1 Mon Sep 17 00:00:00 2001 From: jane-olszewska Date: Mon, 6 Feb 2017 18:09:57 +0000 Subject: [PATCH 1/4] Fixed comment token extraction: will no longer read one character from the next line --- src/Language/Lexer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Lexer.php b/src/Language/Lexer.php index 623e1c5..121016d 100644 --- a/src/Language/Lexer.php +++ b/src/Language/Lexer.php @@ -492,7 +492,7 @@ class Lexer $line, $col, $prev, - mb_substr($body, $start + 1, $position - $start + 1, 'UTF-8') + mb_substr($body, $start + 1, $position - $start, 'UTF-8') ); } } From dd31ab2b80f4b97cef8ad1106e423fc33eea3a52 Mon Sep 17 00:00:00 2001 From: jane-olszewska Date: Fri, 3 Feb 2017 13:03:29 +0000 Subject: [PATCH 2/4] Added a description field to schema type definition classes --- src/Language/AST/EnumTypeDefinitionNode.php | 5 ++ src/Language/AST/EnumValueDefinitionNode.php | 5 ++ src/Language/AST/FieldDefinitionNode.php | 5 ++ .../AST/InputObjectTypeDefinitionNode.php | 5 ++ src/Language/AST/InputValueDefinitionNode.php | 5 ++ .../AST/InterfaceTypeDefinitionNode.php | 5 ++ src/Language/AST/ObjectTypeDefinitionNode.php | 5 ++ src/Language/AST/ScalarTypeDefinitionNode.php | 5 ++ src/Language/AST/UnionTypeDefinitionNode.php | 5 ++ tests/Language/SchemaParserTest.php | 57 ++++++++++++------- 10 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/Language/AST/EnumTypeDefinitionNode.php b/src/Language/AST/EnumTypeDefinitionNode.php index 2ceb6a4..3d1113c 100644 --- a/src/Language/AST/EnumTypeDefinitionNode.php +++ b/src/Language/AST/EnumTypeDefinitionNode.php @@ -22,4 +22,9 @@ class EnumTypeDefinitionNode extends Node implements TypeDefinitionNode * @var EnumValueDefinitionNode[] */ public $values; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/EnumValueDefinitionNode.php b/src/Language/AST/EnumValueDefinitionNode.php index 6cd2c14..45e6b2d 100644 --- a/src/Language/AST/EnumValueDefinitionNode.php +++ b/src/Language/AST/EnumValueDefinitionNode.php @@ -17,4 +17,9 @@ class EnumValueDefinitionNode extends Node * @var DirectiveNode[] */ public $directives; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/FieldDefinitionNode.php b/src/Language/AST/FieldDefinitionNode.php index b271e78..97639d3 100644 --- a/src/Language/AST/FieldDefinitionNode.php +++ b/src/Language/AST/FieldDefinitionNode.php @@ -27,4 +27,9 @@ class FieldDefinitionNode extends Node * @var DirectiveNode[] */ public $directives; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/InputObjectTypeDefinitionNode.php b/src/Language/AST/InputObjectTypeDefinitionNode.php index 19df4f2..17e0d07 100644 --- a/src/Language/AST/InputObjectTypeDefinitionNode.php +++ b/src/Language/AST/InputObjectTypeDefinitionNode.php @@ -22,4 +22,9 @@ class InputObjectTypeDefinitionNode extends Node implements TypeDefinitionNode * @var InputValueDefinitionNode[] */ public $fields; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/InputValueDefinitionNode.php b/src/Language/AST/InputValueDefinitionNode.php index 5786d58..7dc65c4 100644 --- a/src/Language/AST/InputValueDefinitionNode.php +++ b/src/Language/AST/InputValueDefinitionNode.php @@ -27,4 +27,9 @@ class InputValueDefinitionNode extends Node * @var DirectiveNode[] */ public $directives; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/InterfaceTypeDefinitionNode.php b/src/Language/AST/InterfaceTypeDefinitionNode.php index e16f222..60d2fd5 100644 --- a/src/Language/AST/InterfaceTypeDefinitionNode.php +++ b/src/Language/AST/InterfaceTypeDefinitionNode.php @@ -22,4 +22,9 @@ class InterfaceTypeDefinitionNode extends Node implements TypeDefinitionNode * @var FieldDefinitionNode[] */ public $fields = []; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/ObjectTypeDefinitionNode.php b/src/Language/AST/ObjectTypeDefinitionNode.php index e39f8bb..82d77c4 100644 --- a/src/Language/AST/ObjectTypeDefinitionNode.php +++ b/src/Language/AST/ObjectTypeDefinitionNode.php @@ -27,4 +27,9 @@ class ObjectTypeDefinitionNode extends Node implements TypeDefinitionNode * @var FieldDefinitionNode[] */ public $fields; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/ScalarTypeDefinitionNode.php b/src/Language/AST/ScalarTypeDefinitionNode.php index 1609911..483fb89 100644 --- a/src/Language/AST/ScalarTypeDefinitionNode.php +++ b/src/Language/AST/ScalarTypeDefinitionNode.php @@ -17,4 +17,9 @@ class ScalarTypeDefinitionNode extends Node implements TypeDefinitionNode * @var DirectiveNode[] */ public $directives; + + /** + * @var string + */ + public $description; } diff --git a/src/Language/AST/UnionTypeDefinitionNode.php b/src/Language/AST/UnionTypeDefinitionNode.php index 052bb7d..7653b75 100644 --- a/src/Language/AST/UnionTypeDefinitionNode.php +++ b/src/Language/AST/UnionTypeDefinitionNode.php @@ -22,4 +22,9 @@ class UnionTypeDefinitionNode extends Node implements TypeDefinitionNode * @var NamedTypeNode[] */ public $types = []; + + /** + * @var string + */ + public $description; } diff --git a/tests/Language/SchemaParserTest.php b/tests/Language/SchemaParserTest.php index fd10108..16397aa 100644 --- a/tests/Language/SchemaParserTest.php +++ b/tests/Language/SchemaParserTest.php @@ -54,7 +54,8 @@ type Hello { $loc(16, 29) ) ], - 'loc' => $loc(1, 31) + 'loc' => $loc(1, 31), + 'description' => null ] ], 'loc' => $loc(0, 31) @@ -93,7 +94,8 @@ extend type Hello { $loc(23, 36) ) ], - 'loc' => $loc(8, 38) + 'loc' => $loc(8, 38), + 'description' => null ], 'loc' => $loc(1, 38) ] @@ -136,7 +138,8 @@ type Hello { $loc(16,30) ) ], - 'loc' => $loc(1,32) + 'loc' => $loc(1,32), + 'description' => null ] ], 'loc' => $loc(0,32) @@ -165,7 +168,8 @@ type Hello { ], 'directives' => [], 'fields' => [], - 'loc' => $loc(0,31) + 'loc' => $loc(0,31), + 'description' => null ] ], 'loc' => $loc(0,31) @@ -195,7 +199,8 @@ type Hello { ], 'directives' => [], 'fields' => [], - 'loc' => $loc(0, 33) + 'loc' => $loc(0, 33), + 'description' => null ] ], 'loc' => $loc(0, 33) @@ -221,7 +226,8 @@ type Hello { 'name' => $this->nameNode('Hello', $loc(5, 10)), 'directives' => [], 'values' => [$this->enumValueNode('WORLD', $loc(13, 18))], - 'loc' => $loc(0, 20) + 'loc' => $loc(0, 20), + 'description' => null ] ], 'loc' => $loc(0, 20) @@ -250,7 +256,8 @@ type Hello { $this->enumValueNode('WO', $loc(13, 15)), $this->enumValueNode('RLD', $loc(17, 20)) ], - 'loc' => $loc(0, 22) + 'loc' => $loc(0, 22), + 'description' => null ] ], 'loc' => $loc(0, 22) @@ -285,7 +292,8 @@ interface Hello { $loc(21, 34) ) ], - 'loc' => $loc(1, 36) + 'loc' => $loc(1, 36), + 'description' => null ] ], 'loc' => $loc(0,36) @@ -328,7 +336,8 @@ type Hello { $loc(16, 44) ) ], - 'loc' => $loc(1, 46) + 'loc' => $loc(1, 46), + 'description' => null ] ], 'loc' => $loc(0, 46) @@ -372,7 +381,8 @@ type Hello { $loc(16, 51) ) ], - 'loc' => $loc(1, 53) + 'loc' => $loc(1, 53), + 'description' => null ] ], 'loc' => $loc(0, 53) @@ -415,7 +425,8 @@ type Hello { $loc(16, 47) ) ], - 'loc' => $loc(1, 49) + 'loc' => $loc(1, 49), + 'description' => null ] ], 'loc' => $loc(0, 49) @@ -465,7 +476,8 @@ type Hello { $loc(16, 59) ) ], - 'loc' => $loc(1, 61) + 'loc' => $loc(1, 61), + 'description' => null ] ], 'loc' => $loc(0, 61) @@ -490,7 +502,8 @@ type Hello { 'name' => $this->nameNode('Hello', $loc(6, 11)), 'directives' => [], 'types' => [$this->typeNode('World', $loc(14, 19))], - 'loc' => $loc(0, 19) + 'loc' => $loc(0, 19), + 'description' => null ] ], 'loc' => $loc(0, 19) @@ -519,7 +532,8 @@ type Hello { $this->typeNode('Wo', $loc(14, 16)), $this->typeNode('Rld', $loc(19, 22)) ], - 'loc' => $loc(0, 22) + 'loc' => $loc(0, 22), + 'description' => null ] ], 'loc' => $loc(0, 22) @@ -542,7 +556,8 @@ type Hello { 'kind' => NodeKind::SCALAR_TYPE_DEFINITION, 'name' => $this->nameNode('Hello', $loc(7, 12)), 'directives' => [], - 'loc' => $loc(0, 12) + 'loc' => $loc(0, 12), + 'description' => null ] ], 'loc' => $loc(0, 12) @@ -577,7 +592,8 @@ input Hello { $loc(17, 30) ) ], - 'loc' => $loc(1, 32) + 'loc' => $loc(1, 32), + 'description' => null ] ], 'loc' => $loc(0, 32) @@ -629,7 +645,8 @@ input Hello { 'arguments' => $args, 'type' => $type, 'directives' => [], - 'loc' => $loc + 'loc' => $loc, + 'description' => null ]; } @@ -639,7 +656,8 @@ input Hello { 'kind' => NodeKind::ENUM_VALUE_DEFINITION, 'name' => $this->nameNode($name, $loc), 'directives' => [], - 'loc' => $loc + 'loc' => $loc, + 'description' => null ]; } @@ -651,7 +669,8 @@ input Hello { 'type' => $type, 'defaultValue' => $defaultValue, 'directives' => [], - 'loc' => $loc + 'loc' => $loc, + 'description' => null ]; } } From 060dc515952488bd4d6b3900a7127839e7b2bd35 Mon Sep 17 00:00:00 2001 From: jane-olszewska Date: Fri, 3 Feb 2017 14:54:47 +0000 Subject: [PATCH 3/4] Set schema element description to strings retrieved from a continuous chunk of comment tokens immediately preceding the element --- src/Language/Parser.php | 68 +++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/src/Language/Parser.php b/src/Language/Parser.php index a793278..e19f667 100644 --- a/src/Language/Parser.php +++ b/src/Language/Parser.php @@ -910,10 +910,13 @@ class Parser $name = $this->parseName(); $directives = $this->parseDirectives(); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new ScalarTypeDefinitionNode([ 'name' => $name, 'directives' => $directives, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -935,12 +938,15 @@ class Parser Token::BRACE_R ); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new ObjectTypeDefinitionNode([ 'name' => $name, 'interfaces' => $interfaces, 'directives' => $directives, 'fields' => $fields, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -972,12 +978,15 @@ class Parser $type = $this->parseTypeReference(); $directives = $this->parseDirectives(); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new FieldDefinitionNode([ 'name' => $name, 'arguments' => $args, 'type' => $type, 'directives' => $directives, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -1007,12 +1016,14 @@ class Parser $defaultValue = $this->parseConstValue(); } $directives = $this->parseDirectives(); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); return new InputValueDefinitionNode([ 'name' => $name, 'type' => $type, 'defaultValue' => $defaultValue, 'directives' => $directives, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -1032,11 +1043,14 @@ class Parser Token::BRACE_R ); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new InterfaceTypeDefinitionNode([ 'name' => $name, 'directives' => $directives, 'fields' => $fields, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -1053,11 +1067,14 @@ class Parser $this->expect(Token::EQUALS); $types = $this->parseUnionMembers(); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new UnionTypeDefinitionNode([ 'name' => $name, 'directives' => $directives, 'types' => $types, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -1093,11 +1110,14 @@ class Parser Token::BRACE_R ); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new EnumTypeDefinitionNode([ 'name' => $name, 'directives' => $directives, 'values' => $values, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -1110,10 +1130,13 @@ class Parser $name = $this->parseName(); $directives = $this->parseDirectives(); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new EnumValueDefinitionNode([ 'name' => $name, 'directives' => $directives, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -1133,11 +1156,14 @@ class Parser Token::BRACE_R ); + $description = $this->getDescriptionFromAdjacentCommentTokens($start); + return new InputObjectTypeDefinitionNode([ 'name' => $name, 'directives' => $directives, 'fields' => $fields, - 'loc' => $this->loc($start) + 'loc' => $this->loc($start), + 'description' => $description ]); } @@ -1193,4 +1219,28 @@ class Parser } while ($this->skip(Token::PIPE)); return $locations; } + + /** + * @param Token $nameToken + * @return null|string + */ + private function getDescriptionFromAdjacentCommentTokens(Token $nameToken) + { + $description = null; + + $currentToken = $nameToken; + $previousToken = $currentToken->prev; + + while ($previousToken->kind == Token::COMMENT + && ($previousToken->line + 1) == $currentToken->line + ) { + $description = $previousToken->value . $description; + + // walk the tokens backwards until no longer adjacent comments + $currentToken = $previousToken; + $previousToken = $currentToken->prev; + } + + return $description; + } } From 008fd20498b6634b9753b411a02bb6239f5afe98 Mon Sep 17 00:00:00 2001 From: jane-olszewska Date: Mon, 6 Feb 2017 19:11:12 +0000 Subject: [PATCH 4/4] Added test for adding a schema element description in comments --- tests/Language/SchemaParserTest.php | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/Language/SchemaParserTest.php b/tests/Language/SchemaParserTest.php index 16397aa..736ebf9 100644 --- a/tests/Language/SchemaParserTest.php +++ b/tests/Language/SchemaParserTest.php @@ -614,6 +614,47 @@ input Hello { Parser::parse($body); } + /** + * @it Simple type + */ + public function testSimpleTypeDescriptionInComments() + { + $body = ' +# This is a simple type description. +# It is multiline *and includes formatting*. +type Hello { + # And this is a field description + world: String +}'; + $doc = Parser::parse($body); + $loc = function($start, $end) {return TestUtils::locArray($start, $end);}; + + $fieldNode = $this->fieldNode( + $this->nameNode('world', $loc(134, 139)), + $this->typeNode('String', $loc(141, 147)), + $loc(134, 147) + ); + $fieldNode['description'] = " And this is a field description\n"; + $expected = [ + 'kind' => NodeKind::DOCUMENT, + 'definitions' => [ + [ + 'kind' => NodeKind::OBJECT_TYPE_DEFINITION, + 'name' => $this->nameNode('Hello', $loc(88, 93)), + 'interfaces' => [], + 'directives' => [], + 'fields' => [ + $fieldNode + ], + 'loc' => $loc(83, 149), + 'description' => " This is a simple type description.\n It is multiline *and includes formatting*.\n" + ] + ], + 'loc' => $loc(0, 149) + ]; + $this->assertEquals($expected, TestUtils::nodeToArray($doc)); + } + private function typeNode($name, $loc) { return [