SDL Spec changes

This adds the recent changes to the SDL proposal.

ref: graphql/graphql-js#1117
This commit is contained in:
Daniel Tschinder 2018-02-11 21:08:53 +01:00
parent 74854d55a0
commit b5106a06c9
20 changed files with 580 additions and 116 deletions

View File

@ -19,7 +19,7 @@ class EnumTypeDefinitionNode extends Node implements TypeDefinitionNode
public $directives;
/**
* @var EnumValueDefinitionNode[]
* @var EnumValueDefinitionNode[]|null
*/
public $values;

View File

@ -0,0 +1,25 @@
<?php
namespace GraphQL\Language\AST;
class EnumTypeExtensionNode extends Node implements TypeExtensionNode
{
/**
* @var string
*/
public $kind = NodeKind::ENUM_TYPE_EXTENSION;
/**
* @var NameNode
*/
public $name;
/**
* @var DirectiveNode[]|null
*/
public $directives;
/**
* @var EnumValueDefinitionNode[]|null
*/
public $values;
}

View File

@ -14,12 +14,12 @@ class InputObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
public $name;
/**
* @var DirectiveNode[]
* @var DirectiveNode[]|null
*/
public $directives;
/**
* @var InputValueDefinitionNode[]
* @var InputValueDefinitionNode[]|null
*/
public $fields;

View File

@ -0,0 +1,25 @@
<?php
namespace GraphQL\Language\AST;
class InputObjectTypeExtensionNode extends Node implements TypeExtensionNode
{
/**
* @var string
*/
public $kind = NodeKind::INPUT_OBJECT_TYPE_EXTENSION;
/**
* @var NameNode
*/
public $name;
/**
* @var DirectiveNode[]|null
*/
public $directives;
/**
* @var InputValueDefinitionNode[]|null
*/
public $fields;
}

View File

@ -14,14 +14,14 @@ class InterfaceTypeDefinitionNode extends Node implements TypeDefinitionNode
public $name;
/**
* @var DirectiveNode[]
* @var DirectiveNode[]|null
*/
public $directives;
/**
* @var FieldDefinitionNode[]
* @var FieldDefinitionNode[]|null
*/
public $fields = [];
public $fields;
/**
* @var StringValueNode|null

View File

@ -0,0 +1,25 @@
<?php
namespace GraphQL\Language\AST;
class InterfaceTypeExtensionNode extends Node implements TypeExtensionNode
{
/**
* @var string
*/
public $kind = NodeKind::INTERFACE_TYPE_EXTENSION;
/**
* @var NameNode
*/
public $name;
/**
* @var DirectiveNode[]|null
*/
public $directives;
/**
* @var FieldDefinitionNode[]|null
*/
public $fields;
}

View File

@ -65,7 +65,12 @@ class NodeKind
// Type Extensions
const SCALAR_TYPE_EXTENSION = 'ScalarTypeExtension';
const OBJECT_TYPE_EXTENSION = 'ObjectTypeExtension';
const INTERFACE_TYPE_EXTENSION = 'InterfaceTypeExtension';
const UNION_TYPE_EXTENSION = 'UnionTypeExtension';
const ENUM_TYPE_EXTENSION = 'EnumTypeExtension';
const INPUT_OBJECT_TYPE_EXTENSION = 'InputObjectTypeExtension';
// Directive Definitions
@ -127,7 +132,12 @@ class NodeKind
NodeKind::INPUT_OBJECT_TYPE_DEFINITION =>InputObjectTypeDefinitionNode::class,
// Type Extensions
NodeKind::SCALAR_TYPE_EXTENSION => ScalarTypeExtensionNode::class,
NodeKind::OBJECT_TYPE_EXTENSION => ObjectTypeExtensionNode::class,
NodeKind::INTERFACE_TYPE_EXTENSION => InterfaceTypeExtensionNode::class,
NodeKind::UNION_TYPE_EXTENSION => UnionTypeExtensionNode::class,
NodeKind::ENUM_TYPE_EXTENSION => EnumTypeExtensionNode::class,
NodeKind::INPUT_OBJECT_TYPE_EXTENSION => InputObjectTypeExtensionNode::class,
// Directive Definitions
NodeKind::DIRECTIVE_DEFINITION => DirectiveDefinitionNode::class

View File

@ -19,12 +19,12 @@ class ObjectTypeDefinitionNode extends Node implements TypeDefinitionNode
public $interfaces = [];
/**
* @var DirectiveNode[]
* @var DirectiveNode[]|null
*/
public $directives;
/**
* @var FieldDefinitionNode[]
* @var FieldDefinitionNode[]|null
*/
public $fields;

View File

@ -0,0 +1,20 @@
<?php
namespace GraphQL\Language\AST;
class ScalarTypeExtensionNode extends Node implements TypeExtensionNode
{
/**
* @var string
*/
public $kind = NodeKind::SCALAR_TYPE_EXTENSION;
/**
* @var NameNode
*/
public $name;
/**
* @var DirectiveNode[]|null
*/
public $directives;
}

View File

@ -5,6 +5,11 @@ interface TypeExtensionNode extends TypeSystemDefinitionNode
{
/**
export type TypeExtensionNode =
| ObjectTypeExtensionNode;
| ScalarTypeExtensionNode
| ObjectTypeExtensionNode
| InterfaceTypeExtensionNode
| UnionTypeExtensionNode
| EnumTypeExtensionNode
| InputObjectTypeExtensionNode;
*/
}

View File

@ -19,9 +19,9 @@ class UnionTypeDefinitionNode extends Node implements TypeDefinitionNode
public $directives;
/**
* @var NamedTypeNode[]
* @var NamedTypeNode[]|null
*/
public $types = [];
public $types;
/**
* @var StringValueNode|null

View File

@ -0,0 +1,25 @@
<?php
namespace GraphQL\Language\AST;
class UnionTypeExtensionNode extends Node implements TypeExtensionNode
{
/**
* @var string
*/
public $kind = NodeKind::UNION_TYPE_EXTENSION;
/**
* @var NameNode
*/
public $name;
/**
* @var DirectiveNode[]|null
*/
public $directives;
/**
* @var NamedTypeNode[]|null
*/
public $types;
}

View File

@ -4,11 +4,14 @@ namespace GraphQL\Language;
use GraphQL\Language\AST\ArgumentNode;
use GraphQL\Language\AST\DirectiveDefinitionNode;
use GraphQL\Language\AST\EnumTypeDefinitionNode;
use GraphQL\Language\AST\EnumTypeExtensionNode;
use GraphQL\Language\AST\EnumValueDefinitionNode;
use GraphQL\Language\AST\FieldDefinitionNode;
use GraphQL\Language\AST\InputObjectTypeDefinitionNode;
use GraphQL\Language\AST\InputObjectTypeExtensionNode;
use GraphQL\Language\AST\InputValueDefinitionNode;
use GraphQL\Language\AST\InterfaceTypeDefinitionNode;
use GraphQL\Language\AST\InterfaceTypeExtensionNode;
use GraphQL\Language\AST\ListValueNode;
use GraphQL\Language\AST\BooleanValueNode;
use GraphQL\Language\AST\DirectiveNode;
@ -33,6 +36,7 @@ use GraphQL\Language\AST\ObjectValueNode;
use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Language\AST\OperationTypeDefinitionNode;
use GraphQL\Language\AST\ScalarTypeDefinitionNode;
use GraphQL\Language\AST\ScalarTypeExtensionNode;
use GraphQL\Language\AST\SchemaDefinitionNode;
use GraphQL\Language\AST\SelectionSetNode;
use GraphQL\Language\AST\StringValueNode;
@ -40,9 +44,11 @@ use GraphQL\Language\AST\ObjectTypeExtensionNode;
use GraphQL\Language\AST\TypeExtensionNode;
use GraphQL\Language\AST\TypeSystemDefinitionNode;
use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\AST\UnionTypeExtensionNode;
use GraphQL\Language\AST\VariableNode;
use GraphQL\Language\AST\VariableDefinitionNode;
use GraphQL\Error\SyntaxError;
use GraphQL\Type\TypeKind;
/**
* Parses string containing GraphQL query or [type definition](type-system/type-language.md) to Abstract Syntax Tree.
@ -1002,7 +1008,7 @@ class Parser
$name = $this->parseName();
$interfaces = $this->parseImplementsInterfaces();
$directives = $this->parseDirectives(true);
$fields = $this->parseFieldDefinitions();
$fields = $this->parseFieldsDefinition();
return new ObjectTypeDefinitionNode([
'name' => $name,
@ -1033,13 +1039,15 @@ class Parser
* @return FieldDefinitionNode[]|NodeList
* @throws SyntaxError
*/
function parseFieldDefinitions()
function parseFieldsDefinition()
{
return $this->many(
Token::BRACE_L,
[$this, 'parseFieldDefinition'],
Token::BRACE_R
);
return $this->peek(Token::BRACE_L)
? $this->many(
Token::BRACE_L,
[$this, 'parseFieldDefinition'],
Token::BRACE_R
)
: new NodeList([]);
}
/**
@ -1114,7 +1122,7 @@ class Parser
$this->expectKeyword('interface');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$fields = $this->parseFieldDefinitions();
$fields = $this->parseFieldsDefinition();
return new InterfaceTypeDefinitionNode([
'name' => $name,
@ -1136,8 +1144,7 @@ class Parser
$this->expectKeyword('union');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$this->expect(Token::EQUALS);
$types = $this->parseUnionMembers();
$types = $this->parseMemberTypesDefinition();
return new UnionTypeDefinitionNode([
'name' => $name,
@ -1149,22 +1156,23 @@ class Parser
}
/**
* UnionMembers :
* MemberTypes :
* - `|`? NamedType
* - UnionMembers | NamedType
* - MemberTypes | NamedType
*
* @return NamedTypeNode[]
*/
function parseUnionMembers()
function parseMemberTypesDefinition()
{
// Optional leading pipe
$this->skip(Token::PIPE);
$members = [];
do {
$members[] = $this->parseNamedType();
} while ($this->skip(Token::PIPE));
return $members;
$types = [];
if ($this->skip(Token::EQUALS)) {
// Optional leading pipe
$this->skip(Token::PIPE);
do {
$types[] = $this->parseNamedType();
} while ($this->skip(Token::PIPE));
}
return $types;
}
/**
@ -1178,11 +1186,7 @@ class Parser
$this->expectKeyword('enum');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$values = $this->many(
Token::BRACE_L,
[$this, 'parseEnumValueDefinition'],
Token::BRACE_R
);
$values = $this->parseEnumValuesDefinition();
return new EnumTypeDefinitionNode([
'name' => $name,
@ -1193,6 +1197,21 @@ class Parser
]);
}
/**
* @return EnumValueDefinitionNode[]|NodeList
* @throws SyntaxError
*/
function parseEnumValuesDefinition()
{
return $this->peek(Token::BRACE_L)
? $this->many(
Token::BRACE_L,
[$this, 'parseEnumValueDefinition'],
Token::BRACE_R
)
: new NodeList([]);
}
/**
* @return EnumValueDefinitionNode
* @throws SyntaxError
@ -1223,11 +1242,7 @@ class Parser
$this->expectKeyword('input');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$fields = $this->many(
Token::BRACE_L,
[$this, 'parseInputValueDef'],
Token::BRACE_R
);
$fields = $this->parseInputFieldsDefinition();
return new InputObjectTypeDefinitionNode([
'name' => $name,
@ -1239,6 +1254,28 @@ class Parser
}
/**
* @return InputValueDefinitionNode[]|NodeList
* @throws SyntaxError
*/
function parseInputFieldsDefinition() {
return $this->peek(Token::BRACE_L)
? $this->many(
Token::BRACE_L,
[$this, 'parseInputValueDef'],
Token::BRACE_R
)
: new NodeList([]);
}
/**
* TypeExtension :
* - ScalarTypeExtension
* - ObjectTypeExtension
* - InterfaceTypeExtension
* - UnionTypeExtension
* - EnumTypeExtension
* - InputObjectTypeDefinition
*
* @return TypeExtensionNode
* @throws SyntaxError
*/
@ -1248,14 +1285,45 @@ class Parser
if ($keywordToken->kind === Token::NAME) {
switch ($keywordToken->value) {
case 'scalar':
return $this->parseScalarTypeExtension();
case 'type':
return $this->parseObjectTypeExtension();
case 'interface':
return $this->parseInterfaceTypeExtension();
case 'union':
return $this->parseUnionTypeExtension();
case 'enum':
return $this->parseEnumTypeExtension();
case 'input':
return $this->parseInputObjectTypeExtension();
}
}
throw $this->unexpected($keywordToken);
}
/**
* @return ScalarTypeExtensionNode
* @throws SyntaxError
*/
function parseScalarTypeExtension() {
$start = $this->lexer->token;
$this->expectKeyword('extend');
$this->expectKeyword('scalar');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
if (count($directives) === 0) {
throw $this->unexpected();
}
return new ScalarTypeExtensionNode([
'name' => $name,
'directives' => $directives,
'loc' => $this->loc($start)
]);
}
/**
* @return ObjectTypeExtensionNode
* @throws SyntaxError
@ -1267,9 +1335,7 @@ class Parser
$name = $this->parseName();
$interfaces = $this->parseImplementsInterfaces();
$directives = $this->parseDirectives(true);
$fields = $this->peek(Token::BRACE_L)
? $this->parseFieldDefinitions()
: [];
$fields = $this->parseFieldsDefinition();
if (
count($interfaces) === 0 &&
@ -1288,6 +1354,110 @@ class Parser
]);
}
/**
* @return InterfaceTypeExtensionNode
* @throws SyntaxError
*/
function parseInterfaceTypeExtension() {
$start = $this->lexer->token;
$this->expectKeyword('extend');
$this->expectKeyword('interface');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$fields = $this->parseFieldsDefinition();
if (
count($directives) === 0 &&
count($fields) === 0
) {
throw $this->unexpected();
}
return new InterfaceTypeExtensionNode([
'name' => $name,
'directives' => $directives,
'fields' => $fields,
'loc' => $this->loc($start)
]);
}
/**
* @return UnionTypeExtensionNode
* @throws SyntaxError
*/
function parseUnionTypeExtension() {
$start = $this->lexer->token;
$this->expectKeyword('extend');
$this->expectKeyword('union');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$types = $this->parseMemberTypesDefinition();
if (
count($directives) === 0 &&
count($types) === 0
) {
throw $this->unexpected();
}
return new UnionTypeExtensionNode([
'name' => $name,
'directives' => $directives,
'types' => $types,
'loc' => $this->loc($start)
]);
}
/**
* @return EnumTypeExtensionNode
* @throws SyntaxError
*/
function parseEnumTypeExtension() {
$start = $this->lexer->token;
$this->expectKeyword('extend');
$this->expectKeyword('enum');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$values = $this->parseEnumValuesDefinition();
if (
count($directives) === 0 &&
count($values) === 0
) {
throw $this->unexpected();
}
return new EnumTypeExtensionNode([
'name' => $name,
'directives' => $directives,
'values' => $values,
'loc' => $this->loc($start)
]);
}
/**
* @return InputObjectTypeExtensionNode
* @throws SyntaxError
*/
function parseInputObjectTypeExtension() {
$start = $this->lexer->token;
$this->expectKeyword('extend');
$this->expectKeyword('input');
$name = $this->parseName();
$directives = $this->parseDirectives(true);
$fields = $this->parseInputFieldsDefinition();
if (
count($directives) === 0 &&
count($fields) === 0
) {
throw $this->unexpected();
}
return new InputObjectTypeExtensionNode([
'name' => $name,
'directives' => $directives,
'fields' => $fields,
'loc' => $this->loc($start)
]);
}
/**
* DirectiveDefinition :
* - directive @ Name ArgumentsDefinition? on DirectiveLocations

View File

@ -4,11 +4,14 @@ namespace GraphQL\Language;
use GraphQL\Language\AST\ArgumentNode;
use GraphQL\Language\AST\DirectiveDefinitionNode;
use GraphQL\Language\AST\EnumTypeDefinitionNode;
use GraphQL\Language\AST\EnumTypeExtensionNode;
use GraphQL\Language\AST\EnumValueDefinitionNode;
use GraphQL\Language\AST\FieldDefinitionNode;
use GraphQL\Language\AST\InputObjectTypeDefinitionNode;
use GraphQL\Language\AST\InputObjectTypeExtensionNode;
use GraphQL\Language\AST\InputValueDefinitionNode;
use GraphQL\Language\AST\InterfaceTypeDefinitionNode;
use GraphQL\Language\AST\InterfaceTypeExtensionNode;
use GraphQL\Language\AST\ListValueNode;
use GraphQL\Language\AST\BooleanValueNode;
use GraphQL\Language\AST\DirectiveNode;
@ -32,11 +35,13 @@ use GraphQL\Language\AST\ObjectValueNode;
use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Language\AST\OperationTypeDefinitionNode;
use GraphQL\Language\AST\ScalarTypeDefinitionNode;
use GraphQL\Language\AST\ScalarTypeExtensionNode;
use GraphQL\Language\AST\SchemaDefinitionNode;
use GraphQL\Language\AST\SelectionSetNode;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Language\AST\ObjectTypeExtensionNode;
use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\AST\UnionTypeExtensionNode;
use GraphQL\Language\AST\VariableDefinitionNode;
use GraphQL\Utils\Utils;
@ -246,7 +251,9 @@ class Printer
'union',
$def->name,
$this->join($def->directives, ' '),
'= ' . $this->join($def->types, ' | ')
$def->types
? '= ' . $this->join($def->types, ' | ')
: ''
], ' ')
], "\n");
},
@ -278,6 +285,13 @@ class Printer
], ' ')
], "\n");
},
NodeKind::SCALAR_TYPE_EXTENSION => function(ScalarTypeExtensionNode $def) {
return $this->join([
'extend scalar',
$def->name,
$this->join($def->directives, ' '),
], ' ');
},
NodeKind::OBJECT_TYPE_EXTENSION => function(ObjectTypeExtensionNode $def) {
return $this->join([
'extend type',
@ -287,6 +301,40 @@ class Printer
$this->block($def->fields),
], ' ');
},
NodeKind::INTERFACE_TYPE_EXTENSION => function(InterfaceTypeExtensionNode $def) {
return $this->join([
'extend interface',
$def->name,
$this->join($def->directives, ' '),
$this->block($def->fields),
], ' ');
},
NodeKind::UNION_TYPE_EXTENSION => function(UnionTypeExtensionNode $def) {
return $this->join([
'extend union',
$def->name,
$this->join($def->directives, ' '),
$def->types
? '= ' . $this->join($def->types, ' | ')
: ''
], ' ');
},
NodeKind::ENUM_TYPE_EXTENSION => function(EnumTypeExtensionNode $def) {
return $this->join([
'extend enum',
$def->name,
$this->join($def->directives, ' '),
$this->block($def->values),
], ' ');
},
NodeKind::INPUT_OBJECT_TYPE_EXTENSION => function(InputObjectTypeExtensionNode $def) {
return $this->join([
'extend input',
$def->name,
$this->join($def->directives, ' '),
$this->block($def->fields),
], ' ');
},
NodeKind::DIRECTIVE_DEFINITION => function(DirectiveDefinitionNode $def) {
return $this->join([
$def->description,

View File

@ -142,7 +142,14 @@ class Visitor
NodeKind::ENUM_TYPE_DEFINITION => ['description', 'name', 'directives', 'values'],
NodeKind::ENUM_VALUE_DEFINITION => ['description', 'name', 'directives'],
NodeKind::INPUT_OBJECT_TYPE_DEFINITION => ['description', 'name', 'directives', 'fields'],
NodeKind::OBJECT_TYPE_EXTENSION => [ 'name', 'interfaces', 'directives', 'fields' ],
NodeKind::SCALAR_TYPE_EXTENSION => ['name', 'directives'],
NodeKind::OBJECT_TYPE_EXTENSION => ['name', 'interfaces', 'directives', 'fields'],
NodeKind::INTERFACE_TYPE_EXTENSION => ['name', 'directives', 'fields'],
NodeKind::UNION_TYPE_EXTENSION => ['name', 'directives', 'types'],
NodeKind::ENUM_TYPE_EXTENSION => ['name', 'directives', 'values'],
NodeKind::INPUT_OBJECT_TYPE_EXTENSION => ['name', 'directives', 'fields'],
NodeKind::DIRECTIVE_DEFINITION => ['description', 'name', 'arguments', 'locations']
];

View File

@ -251,15 +251,17 @@ class ASTDefinitionBuilder
private function makeFieldDefMap($def)
{
return Utils::keyValMap(
$def->fields,
function ($field) {
return $field->name->value;
},
function ($field) {
return $this->buildField($field);
}
);
return $def->fields
? Utils::keyValMap(
$def->fields,
function ($field) {
return $field->name->value;
},
function ($field) {
return $this->buildField($field);
}
)
: [];
}
private function makeImplementedInterfaces(ObjectTypeDefinitionNode $def)
@ -313,20 +315,22 @@ class ASTDefinitionBuilder
return new EnumType([
'name' => $def->name->value,
'description' => $this->getDescription($def),
'values' => $def->values
? Utils::keyValMap(
$def->values,
function ($enumValue) {
return $enumValue->name->value;
},
function ($enumValue) {
return [
'description' => $this->getDescription($enumValue),
'deprecationReason' => $this->getDeprecationReason($enumValue),
'astNode' => $enumValue
];
}
)
: [],
'astNode' => $def,
'values' => Utils::keyValMap(
$def->values,
function ($enumValue) {
return $enumValue->name->value;
},
function ($enumValue) {
return [
'description' => $this->getDescription($enumValue),
'deprecationReason' => $this->getDeprecationReason($enumValue),
'astNode' => $enumValue
];
}
)
]);
}
@ -335,10 +339,12 @@ class ASTDefinitionBuilder
return new UnionType([
'name' => $def->name->value,
'description' => $this->getDescription($def),
'types' => Utils::map($def->types, function ($typeNode) {
return $this->buildObjectType($typeNode);
}),
'astNode' => $def
'types' => $def->types
? Utils::map($def->types, function ($typeNode) {
return $this->buildObjectType($typeNode);
}):
[],
'astNode' => $def,
]);
}
@ -360,7 +366,9 @@ class ASTDefinitionBuilder
'name' => $def->name->value,
'description' => $this->getDescription($def),
'fields' => function () use ($def) {
return $this->makeInputValues($def->fields);
return $def->fields
? $this->makeInputValues($def->fields)
: [];
},
'astNode' => $def,
]);

View File

@ -67,20 +67,38 @@ class KnownDirectives extends AbstractValidationRule
case 'subscription': return DirectiveLocation::SUBSCRIPTION;
}
break;
case NodeKind::FIELD: return DirectiveLocation::FIELD;
case NodeKind::FRAGMENT_SPREAD: return DirectiveLocation::FRAGMENT_SPREAD;
case NodeKind::INLINE_FRAGMENT: return DirectiveLocation::INLINE_FRAGMENT;
case NodeKind::FRAGMENT_DEFINITION: return DirectiveLocation::FRAGMENT_DEFINITION;
case NodeKind::SCHEMA_DEFINITION: return DirectiveLocation::SCHEMA;
case NodeKind::SCALAR_TYPE_DEFINITION: return DirectiveLocation::SCALAR;
case NodeKind::FIELD:
return DirectiveLocation::FIELD;
case NodeKind::FRAGMENT_SPREAD:
return DirectiveLocation::FRAGMENT_SPREAD;
case NodeKind::INLINE_FRAGMENT:
return DirectiveLocation::INLINE_FRAGMENT;
case NodeKind::FRAGMENT_DEFINITION:
return DirectiveLocation::FRAGMENT_DEFINITION;
case NodeKind::SCHEMA_DEFINITION:
return DirectiveLocation::SCHEMA;
case NodeKind::SCALAR_TYPE_DEFINITION:
case NodeKind::SCALAR_TYPE_EXTENSION:
return DirectiveLocation::SCALAR;
case NodeKind::OBJECT_TYPE_DEFINITION:
case NodeKind::OBJECT_TYPE_EXTENSION: return DirectiveLocation::OBJECT;
case NodeKind::FIELD_DEFINITION: return DirectiveLocation::FIELD_DEFINITION;
case NodeKind::INTERFACE_TYPE_DEFINITION: return DirectiveLocation::IFACE;
case NodeKind::UNION_TYPE_DEFINITION: return DirectiveLocation::UNION;
case NodeKind::ENUM_TYPE_DEFINITION: return DirectiveLocation::ENUM;
case NodeKind::ENUM_VALUE_DEFINITION: return DirectiveLocation::ENUM_VALUE;
case NodeKind::INPUT_OBJECT_TYPE_DEFINITION: return DirectiveLocation::INPUT_OBJECT;
case NodeKind::OBJECT_TYPE_EXTENSION:
return DirectiveLocation::OBJECT;
case NodeKind::FIELD_DEFINITION:
return DirectiveLocation::FIELD_DEFINITION;
case NodeKind::INTERFACE_TYPE_DEFINITION:
case NodeKind::INTERFACE_TYPE_EXTENSION:
return DirectiveLocation::IFACE;
case NodeKind::UNION_TYPE_DEFINITION:
case NodeKind::UNION_TYPE_EXTENSION:
return DirectiveLocation::UNION;
case NodeKind::ENUM_TYPE_DEFINITION:
case NodeKind::ENUM_TYPE_EXTENSION:
return DirectiveLocation::ENUM;
case NodeKind::ENUM_VALUE_DEFINITION:
return DirectiveLocation::ENUM_VALUE;
case NodeKind::INPUT_OBJECT_TYPE_DEFINITION:
case NodeKind::INPUT_OBJECT_TYPE_EXTENSION:
return DirectiveLocation::INPUT_OBJECT;
case NodeKind::INPUT_VALUE_DEFINITION:
$parentNode = $ancestors[count($ancestors) - 3];
return $parentNode instanceof InputObjectTypeDefinitionNode

View File

@ -74,6 +74,14 @@ type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArg): Type @onField
}
type UndefinedType
extend type Foo {
seven(argument: [String]): Type
}
extend type Foo @onType
interface Bar {
one: Type
four(argument: String = "string"): String
@ -83,16 +91,32 @@ interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArg): Type @onField
}
interface UndefinedInterface
extend interface Bar {
two(argument: InputType!): Type
}
extend interface Bar @onInterface
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
union AnnotatedUnionTwo @onUnion = A | B
union UndefinedUnion
extend union Feed = Photo | Video
extend union Feed @onUnion
scalar CustomScalar
scalar AnnotatedScalar @onScalar
extend scalar CustomScalar @onScalar
enum Site {
DESKTOP
MOBILE
@ -103,20 +127,30 @@ enum AnnotatedEnum @onEnum {
OTHER_VALUE
}
enum UndefinedEnum
extend enum Site {
VR
}
extend enum Site @onEnum
input InputType {
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObjectType {
input AnnotatedInput @onInputObject {
annotatedField: Type @onField
}
extend type Foo {
seven(argument: [String]): Type
input UndefinedInput
extend input InputType {
other: Float = 1.23e4
}
extend type Foo @onType
extend input InputType @onInputObject
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

View File

@ -13,20 +13,28 @@ This is a description
of the `Foo` type.
"""
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = {key: "value"}): Type
seven(argument: Int = null): Type
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = {key: "value"}): Type
seven(argument: Int = null): Type
}
type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArg): Type @onField
}
interface Bar {
type UndefinedType
extend type Foo {
seven(argument: [String]): Type
}
extend type Foo @onType
interface Bar {
one: Type
four(argument: String = "string"): String
}
@ -35,49 +43,75 @@ interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArg): Type @onField
}
interface UndefinedInterface
extend interface Bar {
two(argument: InputType!): Type
}
extend interface Bar @onInterface
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
union AnnotatedUnionTwo @onUnion = | A | B
union UndefinedUnion
extend union Feed = Photo | Video
extend union Feed @onUnion
scalar CustomScalar
scalar AnnotatedScalar @onScalar
extend scalar CustomScalar @onScalar
enum Site {
DESKTOP
MOBILE
DESKTOP
MOBILE
}
enum AnnotatedEnum @onEnum {
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
}
enum UndefinedEnum
extend enum Site {
VR
}
extend enum Site @onEnum
input InputType {
key: String!
answer: Int = 42
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObjectType {
annotatedField: Type @onField
input AnnotatedInput @onInputObject {
annotatedField: Type @onField
}
extend type Foo {
seven(argument: [String]): Type
input UndefinedInput
extend input InputType {
other: Float = 1.23e4
}
extend type Foo @onType
extend input InputType @onInputObject
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!)
on FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT
on FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT
directive @include2(if: Boolean!) on
| FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT
| FIELD
| FRAGMENT_SPREAD
| INLINE_FRAGMENT

View File

@ -139,20 +139,30 @@ class KnownDirectivesTest extends TestCase
extend type MyObj @onObject
scalar MyScalar @onScalar
extend scalar MyScalar @onScalar
interface MyInterface @onInterface {
myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition
}
extend interface MyInterface @onInterface
union MyUnion @onUnion = MyObj | Other
extend union MyUnion @onUnion
enum MyEnum @onEnum {
MY_VALUE @onEnumValue
}
extend enum MyEnum @onEnum
input MyInput @onInputObject {
myField: Int @onInputFieldDefinition
}
extend input MyInput @onInputObject
schema @onSchema {
query: MyQuery