Skip to content

Commit 1831c80

Browse files
committed
WIP: implement directives support
1 parent d981317 commit 1831c80

File tree

5 files changed

+80
-27
lines changed

5 files changed

+80
-27
lines changed

src/schema/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,11 @@ pub enum DirectiveLocation {
205205

206206
#[derive(Debug, Clone, PartialEq)]
207207
pub struct DirectiveDefinition {
208+
pub position: Pos,
208209
pub description: Option<String>,
209210
pub name: Name,
210211
pub arguments: Vec<InputValue>,
211-
// TODO(tailhook) probably convert to a bitset
212-
pub locations: HashSet<DirectiveLocation>,
212+
pub locations: Vec<DirectiveLocation>,
213213
}
214214

215215
impl DirectiveLocation {

src/schema/format.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,24 @@ impl Displayable for TypeExtension {
365365

366366
impl Displayable for DirectiveDefinition {
367367
fn display(&self, f: &mut Formatter) {
368-
unimplemented!();
368+
description(&self.description, f);
369+
f.indent();
370+
f.write("directive @");
371+
f.write(&self.name);
372+
format_arguments(&self.arguments, f);
373+
if !self.locations.is_empty() {
374+
f.write(" on ");
375+
let mut first = true;
376+
for loc in &self.locations {
377+
if first {
378+
first = false;
379+
} else {
380+
f.write(" | ");
381+
}
382+
f.write(loc.as_str());
383+
}
384+
}
385+
f.endline();
369386
}
370387
}
371388

@@ -389,22 +406,20 @@ impl_display!(
389406
SchemaDefinition,
390407
TypeDefinition,
391408
TypeExtension,
392-
// ScalarType,
393-
// ScalarTypeExtension,
394-
// ObjectType,
395-
// ObjectTypeExtension,
396-
// Field,
397-
// InputValue,
398-
// InterfaceType,
399-
// InterfaceTypeExtension,
400-
// UnionType,
401-
// UnionTypeExtension,
402-
// EnumType,
403-
// EnumValue,
404-
// EnumTypeExtension,
405-
// InputObjectType,
406-
// InputObjectTypeExtension,
407-
// DirectiveLocation,
408-
// DirectiveDefinition,
409+
ScalarType,
410+
ScalarTypeExtension,
411+
ObjectType,
412+
ObjectTypeExtension,
413+
Field,
414+
InputValue,
415+
InterfaceType,
416+
InterfaceTypeExtension,
417+
UnionType,
418+
UnionTypeExtension,
419+
EnumType,
420+
EnumTypeExtension,
421+
InputObjectType,
422+
InputObjectTypeExtension,
423+
DirectiveDefinition,
409424
);
410425

src/schema/grammar.rs

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use combine::easy::{Error, Errors};
33
use combine::error::StreamError;
44
use combine::combinator::{many, many1, eof, optional, position, choice};
55
use combine::combinator::{sep_by1};
6+
use failure::Fail;
67

78
use tokenizer::{Kind as T, Token, TokenStream};
89
use helpers::{punct, ident, kind, name};
@@ -431,18 +432,52 @@ pub fn input_object_type_extension<'a>(input: &mut TokenStream<'a>)
431432
.parse_stream(input)
432433
}
433434

435+
pub fn directive_locations<'a>(input: &mut TokenStream<'a>)
436+
-> ParseResult<Vec<DirectiveLocation>, TokenStream<'a>>
437+
{
438+
optional(
439+
optional(punct("|"))
440+
.with(sep_by1(
441+
kind(T::Name)
442+
.and_then(|tok| tok.value.parse::<DirectiveLocation>()
443+
.map_err(|e| e.compat())),
444+
punct("|")))
445+
)
446+
.map(|opt| opt.unwrap_or_else(Vec::new))
447+
.parse_stream(input)
448+
}
449+
450+
pub fn directive_definition<'a>(input: &mut TokenStream<'a>)
451+
-> ParseResult<DirectiveDefinition, TokenStream<'a>>
452+
{
453+
(
454+
position(),
455+
ident("directive").and(punct("@")).with(name()),
456+
parser(arguments_definition),
457+
ident("on").with(parser(directive_locations)),
458+
)
459+
.map(|(position, name, arguments, locations)| {
460+
DirectiveDefinition {
461+
position, name, arguments, locations,
462+
description: None, // is filled in type_definition
463+
}
464+
})
465+
.parse_stream(input)
466+
}
467+
434468
pub fn type_definition<'a>(input: &mut TokenStream<'a>)
435469
-> ParseResult<TypeDefinition, TokenStream<'a>>
436470
{
471+
use self::TypeDefinition::*;
437472
(
438473
optional(parser(string)),
439474
choice((
440-
parser(scalar_type).map(TypeDefinition::Scalar),
441-
parser(object_type).map(TypeDefinition::Object),
442-
parser(interface_type).map(TypeDefinition::Interface),
443-
parser(union_type).map(TypeDefinition::Union),
444-
parser(enum_type).map(TypeDefinition::Enum),
445-
parser(input_object_type).map(TypeDefinition::InputObject),
475+
parser(scalar_type).map(Scalar),
476+
parser(object_type).map(Object),
477+
parser(interface_type).map(Interface),
478+
parser(union_type).map(Union),
479+
parser(enum_type).map(Enum),
480+
parser(input_object_type).map(InputObject),
446481
)),
447482
)
448483
// We can't set description inside type definition parser, because
@@ -486,6 +521,7 @@ pub fn definition<'a>(input: &mut TokenStream<'a>)
486521
parser(schema).map(Definition::SchemaDefinition),
487522
parser(type_definition).map(Definition::TypeDefinition),
488523
parser(type_extension).map(Definition::TypeExtension),
524+
parser(directive_definition).map(Definition::DirectiveDefinition),
489525
)).parse_stream(input)
490526
}
491527

tests/schema_roundtrips.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ fn roundtrip2(filename: &str) {
4646
#[test] fn extend_enum() { roundtrip("extend_enum"); }
4747
#[test] fn input_type() { roundtrip("input_type"); }
4848
#[test] fn extend_input() { roundtrip2("extend_input"); }
49+
#[test] fn directive() { roundtrip("directive"); }
4950
// Not yet fully supported
50-
//#[test] fn kitchen_sink() { roundtrip2("kitchen-sink"); }
51+
// #[test] fn kitchen_sink() { roundtrip2("kitchen-sink"); }

tests/schemas/directive.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

0 commit comments

Comments
 (0)