diff --git a/parser/src/graphql.pest b/parser/src/graphql.pest index 1a7fcd5b..15fb2fc6 100644 --- a/parser/src/graphql.pest +++ b/parser/src/graphql.pest @@ -10,7 +10,7 @@ executable_definition = { operation_definition | fragment_definition } operation_definition = { named_operation_definition | selection_set } named_operation_definition = { operation_type ~ name? ~ variable_definitions? ~ directives? ~ selection_set } variable_definitions = { "(" ~ variable_definition* ~ ")" } -variable_definition = { variable ~ ":" ~ type_ ~ default_value? } +variable_definition = { variable ~ ":" ~ type_ ~ directives? ~ default_value? } selection_set = { "{" ~ selection+ ~ "}" } selection = { field | inline_fragment | fragment_spread } @@ -86,6 +86,7 @@ directive_location = { | "FRAGMENT_DEFINITION" | "FRAGMENT_SPREAD" | "INLINE_FRAGMENT" + | "VARIABLE_DEFINITION" | "SCHEMA" | "SCALAR" | "OBJECT" diff --git a/parser/src/parse/executable.rs b/parser/src/parse/executable.rs index 2fc2a1e6..6ec0207d 100644 --- a/parser/src/parse/executable.rs +++ b/parser/src/parse/executable.rs @@ -208,6 +208,8 @@ fn parse_variable_definition( let variable = parse_variable(pairs.next().unwrap(), pc)?; let var_type = parse_type(pairs.next().unwrap(), pc)?; + + let directives = parse_opt_directives(&mut pairs, pc)?; let default_value = parse_if_rule(&mut pairs, Rule::default_value, |pair| { parse_default_value(pair, pc) })?; @@ -218,6 +220,7 @@ fn parse_variable_definition( VariableDefinition { name: variable, var_type, + directives, default_value, }, pos, diff --git a/parser/src/parse/service.rs b/parser/src/parse/service.rs index 9b2c6206..fa71f235 100644 --- a/parser/src/parse/service.rs +++ b/parser/src/parse/service.rs @@ -323,6 +323,7 @@ fn parse_directive_definition( "FRAGMENT_DEFINITION" => DirectiveLocation::FragmentDefinition, "FRAGMENT_SPREAD" => DirectiveLocation::FragmentSpread, "INLINE_FRAGMENT" => DirectiveLocation::InlineFragment, + "VARIABLE_DEFINITION" => DirectiveLocation::VariableDefinition, "SCHEMA" => DirectiveLocation::Schema, "SCALAR" => DirectiveLocation::Scalar, "OBJECT" => DirectiveLocation::Object, diff --git a/parser/src/pos.rs b/parser/src/pos.rs index 3f37e3e7..a52b062f 100644 --- a/parser/src/pos.rs +++ b/parser/src/pos.rs @@ -10,7 +10,7 @@ use std::str::Chars; /// Original position of an element in source code. /// /// You can serialize and deserialize it to the GraphQL `locations` format -/// ([reference](https://spec.graphql.org/June2018/#sec-Errors)). +/// ([reference](https://spec.graphql.org/October2021/#sec-Errors)). #[derive(PartialOrd, Ord, PartialEq, Eq, Clone, Copy, Default, Hash, Serialize, Deserialize)] pub struct Pos { /// One-based line number. diff --git a/parser/src/types/executable.rs b/parser/src/types/executable.rs index 88371ac1..0e70b13a 100644 --- a/parser/src/types/executable.rs +++ b/parser/src/types/executable.rs @@ -5,7 +5,7 @@ use async_graphql_value::{ConstValue, Name, Value}; /// An executable GraphQL file or request string. /// -/// [Reference](https://spec.graphql.org/June2018/#ExecutableDocument). +/// [Reference](https://spec.graphql.org/October2021/#ExecutableDocument). #[derive(Debug, Clone)] pub struct ExecutableDocument { /// The operations of the document. @@ -93,7 +93,7 @@ enum OperationsIterInner<'a> { /// A GraphQL operation, such as `mutation($content:String!) { makePost(content: $content) { id } }`. /// -/// [Reference](https://spec.graphql.org/June2018/#OperationDefinition). +/// [Reference](https://spec.graphql.org/October2021/#OperationDefinition). #[derive(Debug, Clone)] pub struct OperationDefinition { /// The type of operation. @@ -108,13 +108,15 @@ pub struct OperationDefinition { /// A variable definition inside a list of variable definitions, for example `$name:String!`. /// -/// [Reference](https://spec.graphql.org/June2018/#VariableDefinition). +/// [Reference](https://spec.graphql.org/October2021/#VariableDefinition). #[derive(Debug, Clone)] pub struct VariableDefinition { /// The name of the variable, without the preceding `$`. pub name: Positioned, /// The type of the variable. pub var_type: Positioned, + /// The variable's directives. + pub directives: Vec>, /// The optional default value of the variable. pub default_value: Option>, } @@ -139,7 +141,7 @@ impl VariableDefinition { /// A set of fields to be selected, for example `{ name age }`. /// -/// [Reference](https://spec.graphql.org/June2018/#SelectionSet). +/// [Reference](https://spec.graphql.org/October2021/#SelectionSet). #[derive(Debug, Default, Clone)] pub struct SelectionSet { /// The fields to be selected. @@ -148,7 +150,7 @@ pub struct SelectionSet { /// A part of an object to be selected; a single field, a fragment spread or an inline fragment. /// -/// [Reference](https://spec.graphql.org/June2018/#Selection). +/// [Reference](https://spec.graphql.org/October2021/#Selection). #[derive(Debug, Clone)] pub enum Selection { /// Select a single field, such as `name` or `weightKilos: weight(unit: KILOGRAMS)`. @@ -182,7 +184,7 @@ impl Selection { /// A field being selected on an object, such as `name` or `weightKilos: weight(unit: KILOGRAMS)`. /// -/// [Reference](https://spec.graphql.org/June2018/#Field). +/// [Reference](https://spec.graphql.org/October2021/#Field). #[derive(Debug, Clone)] pub struct Field { /// The optional field alias. @@ -217,7 +219,7 @@ impl Field { /// A fragment selector, such as `... userFields`. /// -/// [Reference](https://spec.graphql.org/June2018/#FragmentSpread). +/// [Reference](https://spec.graphql.org/October2021/#FragmentSpread). #[derive(Debug, Clone)] pub struct FragmentSpread { /// The name of the fragment being selected. @@ -228,7 +230,7 @@ pub struct FragmentSpread { /// An inline fragment selector, such as `... on User { name }`. /// -/// [Reference](https://spec.graphql.org/June2018/#InlineFragment). +/// [Reference](https://spec.graphql.org/October2021/#InlineFragment). #[derive(Debug, Clone)] pub struct InlineFragment { /// The type condition. @@ -241,7 +243,7 @@ pub struct InlineFragment { /// The definition of a fragment, such as `fragment userFields on User { name age }`. /// -/// [Reference](https://spec.graphql.org/June2018/#FragmentDefinition). +/// [Reference](https://spec.graphql.org/October2021/#FragmentDefinition). #[derive(Debug, Clone)] pub struct FragmentDefinition { /// The type this fragment operates on. @@ -254,7 +256,7 @@ pub struct FragmentDefinition { /// A type a fragment can apply to (`on` followed by the type). /// -/// [Reference](https://spec.graphql.org/June2018/#TypeCondition). +/// [Reference](https://spec.graphql.org/October2021/#TypeCondition). #[derive(Debug, Clone)] pub struct TypeCondition { /// The type this fragment applies to. diff --git a/parser/src/types/mod.rs b/parser/src/types/mod.rs index b52e35d2..151fa94f 100644 --- a/parser/src/types/mod.rs +++ b/parser/src/types/mod.rs @@ -4,7 +4,7 @@ //! [`ServiceDocument`](struct.ServiceDocument.html), representing an executable GraphQL query and a //! GraphQL service respectively. //! -//! This follows the [June 2018 edition of the GraphQL spec](https://spec.graphql.org/June2018/). +//! This follows the [June 2018 edition of the GraphQL spec](https://spec.graphql.org/October2021/). mod executable; mod service; @@ -19,7 +19,7 @@ pub use service::*; /// The type of an operation; `query`, `mutation` or `subscription`. /// -/// [Reference](https://spec.graphql.org/June2018/#OperationType). +/// [Reference](https://spec.graphql.org/October2021/#OperationType). #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum OperationType { /// A query. @@ -42,7 +42,7 @@ impl Display for OperationType { /// A GraphQL type, for example `String` or `[String!]!`. /// -/// [Reference](https://spec.graphql.org/June2018/#Type). +/// [Reference](https://spec.graphql.org/October2021/#Type). #[derive(Debug, PartialEq, Eq, Clone)] pub struct Type { /// The base type. @@ -105,7 +105,7 @@ impl Display for BaseType { /// from [`Directive`](struct.Directive.html) in that it uses [`ConstValue`](enum.ConstValue.html) /// instead of [`Value`](enum.Value.html). /// -/// [Reference](https://spec.graphql.org/June2018/#Directive). +/// [Reference](https://spec.graphql.org/October2021/#Directive). #[derive(Debug, Clone)] pub struct ConstDirective { /// The name of the directive. @@ -140,7 +140,7 @@ impl ConstDirective { /// A GraphQL directive, such as `@deprecated(reason: "Use the other field")`. /// -/// [Reference](https://spec.graphql.org/June2018/#Directive). +/// [Reference](https://spec.graphql.org/October2021/#Directive). #[derive(Debug, Clone)] pub struct Directive { /// The name of the directive. diff --git a/parser/src/types/service.rs b/parser/src/types/service.rs index 2a3e81f5..f5e2bcdb 100644 --- a/parser/src/types/service.rs +++ b/parser/src/types/service.rs @@ -5,7 +5,7 @@ use async_graphql_value::Name; /// A GraphQL file or request string defining a GraphQL service. /// -/// [Reference](https://spec.graphql.org/June2018/#Document). +/// [Reference](https://spec.graphql.org/October2021/#Document). #[derive(Debug, Clone)] pub struct ServiceDocument { /// The definitions of this document. @@ -14,8 +14,8 @@ pub struct ServiceDocument { /// A definition concerning the type system of a GraphQL service. /// -/// [Reference](https://spec.graphql.org/June2018/#TypeSystemDefinition). This enum also covers -/// [extensions](https://spec.graphql.org/June2018/#TypeSystemExtension). +/// [Reference](https://spec.graphql.org/October2021/#TypeSystemDefinition). This enum also covers +/// [extensions](https://spec.graphql.org/October2021/#TypeSystemExtension). #[derive(Debug, Clone)] pub enum TypeSystemDefinition { /// The definition of the schema of the service. @@ -28,8 +28,8 @@ pub enum TypeSystemDefinition { /// The definition of the schema in a GraphQL service. /// -/// [Reference](https://spec.graphql.org/June2018/#SchemaDefinition). This also covers -/// [extensions](https://spec.graphql.org/June2018/#SchemaExtension). +/// [Reference](https://spec.graphql.org/October2021/#SchemaDefinition). This also covers +/// [extensions](https://spec.graphql.org/October2021/#SchemaExtension). #[derive(Debug, Clone)] pub struct SchemaDefinition { /// Whether the schema is an extension of another schema. @@ -46,8 +46,8 @@ pub struct SchemaDefinition { /// The definition of a type in a GraphQL service. /// -/// [Reference](https://spec.graphql.org/June2018/#TypeDefinition). This also covers -/// [extensions](https://spec.graphql.org/June2018/#TypeExtension). +/// [Reference](https://spec.graphql.org/October2021/#TypeDefinition). This also covers +/// [extensions](https://spec.graphql.org/October2021/#TypeExtension). #[derive(Debug, Clone)] pub struct TypeDefinition { /// Whether the type is an extension of another type. @@ -81,7 +81,7 @@ pub enum TypeKind { /// The definition of an object type. /// -/// [Reference](https://spec.graphql.org/June2018/#ObjectType). +/// [Reference](https://spec.graphql.org/October2021/#ObjectType). #[derive(Debug, Clone)] pub struct ObjectType { /// The interfaces implemented by the object. @@ -92,7 +92,7 @@ pub struct ObjectType { /// The definition of a field inside an object or interface. /// -/// [Reference](https://spec.graphql.org/June2018/#FieldDefinition). +/// [Reference](https://spec.graphql.org/October2021/#FieldDefinition). #[derive(Debug, Clone)] pub struct FieldDefinition { /// The description of the field. @@ -109,7 +109,7 @@ pub struct FieldDefinition { /// The definition of an interface type. /// -/// [Reference](https://spec.graphql.org/June2018/#InterfaceType). +/// [Reference](https://spec.graphql.org/October2021/#InterfaceType). #[derive(Debug, Clone)] pub struct InterfaceType { /// The interfaces implemented by the interface. @@ -120,7 +120,7 @@ pub struct InterfaceType { /// The definition of a union type. /// -/// [Reference](https://spec.graphql.org/June2018/#UnionType). +/// [Reference](https://spec.graphql.org/October2021/#UnionType). #[derive(Debug, Clone)] pub struct UnionType { /// The member types of the union. @@ -129,7 +129,7 @@ pub struct UnionType { /// The definition of an enum. /// -/// [Reference](https://spec.graphql.org/June2018/#EnumType). +/// [Reference](https://spec.graphql.org/October2021/#EnumType). #[derive(Debug, Clone)] pub struct EnumType { /// The possible values of the enum. @@ -138,7 +138,7 @@ pub struct EnumType { /// The definition of a value inside an enum. /// -/// [Reference](https://spec.graphql.org/June2018/#EnumValueDefinition). +/// [Reference](https://spec.graphql.org/October2021/#EnumValueDefinition). #[derive(Debug, Clone)] pub struct EnumValueDefinition { /// The description of the argument. @@ -151,7 +151,7 @@ pub struct EnumValueDefinition { /// The definition of an input object. /// -/// [Reference](https://spec.graphql.org/June2018/#InputObjectType). +/// [Reference](https://spec.graphql.org/October2021/#InputObjectType). #[derive(Debug, Clone)] pub struct InputObjectType { /// The fields of the input object. @@ -160,7 +160,7 @@ pub struct InputObjectType { /// The definition of an input value inside the arguments of a field. /// -/// [Reference](https://spec.graphql.org/June2018/#InputValueDefinition). +/// [Reference](https://spec.graphql.org/October2021/#InputValueDefinition). #[derive(Debug, Clone)] pub struct InputValueDefinition { /// The description of the argument. @@ -177,7 +177,7 @@ pub struct InputValueDefinition { /// The definition of a directive in a service. /// -/// [Reference](https://spec.graphql.org/June2018/#DirectiveDefinition). +/// [Reference](https://spec.graphql.org/October2021/#DirectiveDefinition). #[derive(Debug, Clone)] pub struct DirectiveDefinition { /// The description of the directive. @@ -192,7 +192,7 @@ pub struct DirectiveDefinition { /// Where a directive can apply to. /// -/// [Reference](https://spec.graphql.org/June2018/#DirectiveLocation). +/// [Reference](https://spec.graphql.org/October2021/#DirectiveLocation). #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DirectiveLocation { /// A [query](enum.OperationType.html#variant.Query) [operation](struct.OperationDefinition.html). @@ -233,4 +233,6 @@ pub enum DirectiveLocation { /// An [input value definition](struct.InputValueDefinition.html) on an input object but not a /// field. InputFieldDefinition, + /// An [variable definition](struct.VariableDefinition.html). + VariableDefinition, } diff --git a/parser/tests/executables/variable_directive.graphql b/parser/tests/executables/variable_directive.graphql new file mode 100644 index 00000000..b6a9d07b --- /dev/null +++ b/parser/tests/executables/variable_directive.graphql @@ -0,0 +1,3 @@ +query Foo($a: Int @directive = 10, $b: Int @directive) { + value +} diff --git a/parser/tests/services/directive.graphql b/parser/tests/services/directive.graphql index 401b6f43..456904bd 100644 --- a/parser/tests/services/directive.graphql +++ b/parser/tests/services/directive.graphql @@ -4,3 +4,5 @@ directive @test1(service: String!) on FIELD_DEFINITION directive @test2(service: String!) on FIELD directive @test3(service: String!) on ENUM_VALUE directive @test4(service: String!) on ENUM + +directive @test5(service: String!) on VARIABLE_DEFINITION