Merge pull request #88 from jane-olszewska/schema-description-in-comments

Schema Definition Language: element descriptions can be set through comments
This commit is contained in:
Vladimir Razuvaev 2017-02-07 13:01:36 +07:00 committed by GitHub
commit c2f0749d8e
12 changed files with 184 additions and 29 deletions

View File

@ -22,4 +22,9 @@ class EnumTypeDefinitionNode extends Node implements TypeDefinitionNode
* @var EnumValueDefinitionNode[]
*/
public $values;
/**
* @var string
*/
public $description;
}

View File

@ -17,4 +17,9 @@ class EnumValueDefinitionNode extends Node
* @var DirectiveNode[]
*/
public $directives;
/**
* @var string
*/
public $description;
}

View File

@ -27,4 +27,9 @@ class FieldDefinitionNode extends Node
* @var DirectiveNode[]
*/
public $directives;
/**
* @var string
*/
public $description;
}

View File

@ -22,4 +22,9 @@ class InputObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
* @var InputValueDefinitionNode[]
*/
public $fields;
/**
* @var string
*/
public $description;
}

View File

@ -27,4 +27,9 @@ class InputValueDefinitionNode extends Node
* @var DirectiveNode[]
*/
public $directives;
/**
* @var string
*/
public $description;
}

View File

@ -22,4 +22,9 @@ class InterfaceTypeDefinitionNode extends Node implements TypeDefinitionNode
* @var FieldDefinitionNode[]
*/
public $fields = [];
/**
* @var string
*/
public $description;
}

View File

@ -27,4 +27,9 @@ class ObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
* @var FieldDefinitionNode[]
*/
public $fields;
/**
* @var string
*/
public $description;
}

View File

@ -17,4 +17,9 @@ class ScalarTypeDefinitionNode extends Node implements TypeDefinitionNode
* @var DirectiveNode[]
*/
public $directives;
/**
* @var string
*/
public $description;
}

View File

@ -22,4 +22,9 @@ class UnionTypeDefinitionNode extends Node implements TypeDefinitionNode
* @var NamedTypeNode[]
*/
public $types = [];
/**
* @var string
*/
public $description;
}

View File

@ -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')
);
}
}

View File

@ -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;
}
}

View File

@ -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)
@ -598,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 [
@ -629,7 +686,8 @@ input Hello {
'arguments' => $args,
'type' => $type,
'directives' => [],
'loc' => $loc
'loc' => $loc,
'description' => null
];
}
@ -639,7 +697,8 @@ input Hello {
'kind' => NodeKind::ENUM_VALUE_DEFINITION,
'name' => $this->nameNode($name, $loc),
'directives' => [],
'loc' => $loc
'loc' => $loc,
'description' => null
];
}
@ -651,7 +710,8 @@ input Hello {
'type' => $type,
'defaultValue' => $defaultValue,
'directives' => [],
'loc' => $loc
'loc' => $loc,
'description' => null
];
}
}